Koder / 박성훈
article thumbnail

2차원 배열에서의 Dp는 너무 어려운 거 같다 ㅠ

익숙해질때까지 많이 풀어봐야겠다....

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

 

2169번: 로봇 조종하기

첫째 줄에 N, M(1≤N, M≤1,000)이 주어진다. 다음 N개의 줄에는 M개의 수로 배열이 주어진다. 배열의 각 수는 절댓값이 100을 넘지 않는 정수이다. 이 값은 그 지역의 가치를 나타낸다.

www.acmicpc.net

문제 풀때에 있어 굉장히 어려운 부분이 한군데 있었다.

5 5

10 25 7 8 13

68 24 -78 63 32

12 -69 100 -29 -25

-16 -22 -57 -33 99

7 -76 -11 77 15

테스트케이스에 입력이 이렇게 들어오는데

두번째 줄 첫번째 입력인 68의 경우

단순히 작성하면 78으로 결과가 나오겠지만

실제로는 10 -> 25 -> 24 -> 68 이라는 경로를 지나갈 때 최대값이 나오게 될 것이다.

단순히 작성한경우

68을 계산할때 24에 있는 최대값을 아직 계산하지 않아 볼 수 없기 때문에

왼쪽으로 더해가며 계산 한번, 오른쪽으로 더해가며 계산을 한번

이렇게 두번 해줘서 비교해줬다.

#include <stdio.h>

int max(int a, int b){ return a>b?a:b; }

int n,m;
int input[1001][1001] = {0};
int dp[1001][1001]	  = {0};
int tmpr[1001] 	      = {0};
int tmpl[1001] 	      = {0};

int main(){
	scanf("%d %d", &n, &m);
	for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) scanf("%d", &input[i][j]);
	
	dp[1][1] = input[1][1];
	for(int i=2; i<=m; i++) dp[1][i] += input[1][i] + dp[1][i-1];
	
	for(int i=2; i<=n; i++){
		tmpr[0] =   dp[i-1][1];
		tmpl[m+1] = dp[i-1][m];
		for(int j=1; j<=m; j++) tmpr[j] = max(tmpr[j-1], dp[i-1][j]) + input[i][j];
		for(int j=m; j>=1; j--) tmpl[j] = max(tmpl[j+1], dp[i-1][j]) + input[i][j];
		
		for(int j=1; j<=m; j++) dp[i][j] = max(tmpr[j], tmpl[j]);
	}
	printf("%d\n", dp[n][m]);
	return 0;
}

dp[i][j]는 로봇이 i, j위치에 있을때의 가치의 최댓값이다.

위에서 말한 문제를 해결하기 위해

오른쪽값과 위의 값을 비교하는 tmpr(tmp-righ)이라는 배열과

왼쪽값과 위의 값을 비교하는 tmpl(tmp-left)이라는 배열

두가지를 만들어 각각을 계산하고,

dp[i][j]에는 둘 중의 최대값을 채워넣었다.

이렇게 하면 진짜 최대값을 dp 배열에 집어넣을 수 있게 된다.

그런데 첫번째 줄의 입력에 대해서는 무조건 1,1에서 시작함이 보장되므로

왼쪽값을 비교할 필요가 없다.

그래서 따로 빼서 계산해줬다.

우리가 원하는건 로봇이 n,m위치에 있을때의 가치의 최대값이므로

dp[n][m]을 출력해주면 AC.

반응형