호우동의 개발일지

Today :

article thumbnail

문제 이해 단계

 

https://www.acmicpc.net/problem/9465

세로가 2이고 가로가 n인 스티커가 있는데 각 스티커에는 점수가 적혀있다.

스티커를 뗄 때에는 특징이 있는데
점수를 얻는 스티커의 상하좌우에 있는 스티커는 더 이상 사용 할 수 없다.

이러한 상황일 때, 얻을 수 있는 점수의 최댓값을 구하는 문제

 

 


문제 접근 단계

해당 문제를 풀기 위해서 예제로 처음부터 시뮬레이션을 돌려보도록 하겠다.
시작값 50일 때 움직일 수 있는 칸 목록이다.

움직일 수 있는 칸의 목록


이렇듯 사실상 왼쪽과 아래에 있는 10,30을 제외하면 다 움직일 수 있는 것으로 보인다.
하지만 우리는 스티커 점수의 최댓값을 구하는 것이다.

썸네일

이렇듯 100, 20,10은 50뿐만 아니라 다른 수에서 접근할 수 있다.
즉 굳이 50에서 바로 접근하지 않아도 된다.

예를 들어 100이란 숫자는 50에서 바로 접근하면 50+100= 150인데
50을 한번 더 거쳐서 가면 50+50+100 = 200으로 더 큰 값을 갖게 된다.

즉 50에서 접근할 수 있는 수는
50과 70 즉 50을 x라고 뒀을 때 x+1과 x+2가 된다.

이 성질은 50에 국한된 것이 아니라 모든 수에서도 같을 것이다.

그렇기 때문에 이를 재귀함수로 구현하면 스코어의 최댓값을 구할 수 있을 것이다.

어떤 수 x가 있을 때, 해당 수는 x-1칸 또는 x-2칸 중
합의 최댓값이 더 큰 것이 접근했을 것이다.

위의 2N을 2차원 배열로 표현했을 때 d라고 한다면

d [i][1] = max(d [i-1][0], d [i-2][0]) + 그 칸의 값
d [i][0] = max(d [i-1][1], d [i-2][1]) + 그 칸의 값
이 될 것이다.

여기서 왜 -1,-2까지만 따져보냐면
-3부터는 -1과 -2와 동일한 모양이 나온다.

거기에서 값만 빠지는 것이기 때문에
-1과 -2보다 작을 수밖에 없어 최댓값이 될 수 없다.

이제 자세한 것은 코드에서 설명하겠다.

 

 


문제 구현 단계

#include <iostream>
using namespace std;

int d[100001][2];
int v[100001][2];

int main(){
    cin.tie(0);cout.tie(0); ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while(T--){
        int n;
        cin >> n;
        for(int i = 0; i <= n; i++)
            for(int j = 0; j < 2; j++){
                d[i][j] = 0;
            }
        for(int i = 1; i<= n; i++) cin >> v[i][0];
        for(int i = 1; i<= n; i++) cin >> v[i][1];

        d[1][0] = v[1][0];
        d[1][1] = v[1][1];
        int ans = max(d[1][0],d[1][1]);
        for(int i = 2; i <= n; i++){
            d[i][0] = max(d[i-1][1],d[i-2][1]) + v[i][0];
            d[i][1] = max(d[i-1][0],d[i-2][0]) + v[i][1];
            int value = max(d[i][0],d[i][1]);
            ans = max(ans,value);
        }
        cout << ans << "\n";
    }
}

ans 밑에 있는 반복문 부분이다.

위에서 설명했듯이 0과 1 부분의 max값을 찾은 다음 두 값 중 더 큰 값을 value로 설정한다.

그리고 그 값을 ans와 비교해 더 크면 그 값을 ans로 처리한다.

int ans = max(d [1][0], d [1][1]); 인 이유는 
반복문은 배열에서 벗어나는 것을 방지하기 위해서 i = 2부터 돌아가기 때문이다.

 

 


시행착오

이 문제를 해결하는데 2~3일 걸렸다.

문제를 해결하는 원리는 잘 파악했는데,
풀면은 잘 올라가다가 98%에서 자꾸 시간초과가 떠서
방법을 자꾸 바꾸다 보니 오래 걸렸다.

그래서 인터넷을 참고했는데, 방법자체는 똑같았는데, 음.. 코드를 잘못 짰다.

정확히는 효율적을 짜지 못했다. 이것도 결국 실력부족이었던 것 같다.
조금 더 열심히 하자