프로그래머스

[프로그래머스_Level2] 땅따먹기

빙수빈수 2021. 7. 21. 15:43

https://programmers.co.kr/learn/courses/30/lessons/12913

 

코딩테스트 연습 - 땅따먹기

땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N행 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟

programmers.co.kr

[문제]

땅따먹기 게임을 하려고 합니다. 땅따먹기 게임의 땅(land)은 총 N행 4열로 이루어져 있고, 모든 칸에는 점수가 쓰여 있습니다. 1행부터 땅을 밟으며 한 행씩 내려올 때, 각 행의 4칸 중 한 칸만 밟으면서 내려와야 합니다. 단, 땅따먹기 게임에는 한 행씩 내려올 때, 같은 열을 연속해서 밟을 수 없는 특수 규칙이 있습니다.

 

예를 들면,

| 1 | 2 | 3 | 5 |

| 5 | 6 | 7 | 8 |

| 4 | 3 | 2 | 1 |

 

로 땅이 주어졌다면, 1행에서 네번째 칸 (5)를 밟았으면, 2행의 네번째 칸 (8)은 밟을 수 없습니다.

마지막 행까지 모두 내려왔을 때, 얻을 수 있는 점수의 최대값을 return하는 solution 함수를 완성해 주세요. 위 예의 경우, 1행의 네번째 칸 (5), 2행의 세번째 칸 (7), 3행의 첫번째 칸 (4) 땅을 밟아 16점이 최고점이 되므로 16을 return 하면 됩니다.

 

[제한 조건]

  • 행의 개수 N : 100,000 이하의 자연수
  • 열의 개수는 4개이고, 땅(land)은 2차원 배열로 주어집니다.
  • 점수 : 100 이하의 자연수

 

[코드]

class Solution {
    int solution(int[][] land) {
        int answer=Integer.MIN_VALUE;
        int[][] dp=new int[land.length][land[0].length];
        
        // dp에 land의 0 번째 행에 있는 값 복사
        for(int i=0;i<land[0].length;i++)
        	dp[0][i]=land[0][i];
        
        // 1 번쨰 행부터 반복
        for(int i=1;i<land.length;i++) {
        	// i번째 행의 j열 탐색
        	for(int j=0;j<land[i].length;j++) {
        		int max=Integer.MIN_VALUE;
        		// 4개의 행 탐색
        		for(int k=0;k<4;k++) {
        			// 현재 열 j와 이전의 열 k가 같다면 해당 땅은 밟을 수 없다.
        			if(j==k)
        				continue;
        			// 나머지 3개의 열에서 최댓값을 찾는다.
        			max=Math.max(max, dp[i-1][k]);
        		}
        		// 위에서 찾은 최댓값과 현재 땅 값을 더해 dp에 저장
        		dp[i][j]=land[i][j]+max;
        	}
        }
        
        // n-1번쨰 행에 저장된 각각의 최댓값들 중 가장 큰 값을 answer에 저장
        for(int i=0;i<4;i++)
        	answer=Math.max(answer, dp[land.length-1][i]);
        
        return answer;
    }
}

 

[고찰]

 이번 문제는 동적 계획법을 사용하여 해결해야 하는 문제였다. 평소 백준 단계별 풀이에서 여러 동적 계획법 문제를 풀어봤지만 여전히 어려운 파트인것 같다.

 위의 문제는 0행은 dp에 미리 복사해 둔 후 1행부터 for문을 시작하면 된다. 각 열에서 0~3까지의 for문을 돌려 해당 열과 같은 값일때는 넘어가고, 나머지 3개의 열에서 최댓값을 찾아 현재 땅 값과 더한 값을 dp에 저장한다. 이 과정을 마지막 행 까지 진행하면 dp의 n-1행에는 마지막 행의 각 땅을 밟았을 때 누적되는 최댓값이 저장되어 있는데 이중 가장 큰 값을 찾아 return 하면 된다.