기술 블로그

17485번 진우의 달 여행 (Large) 본문

알고리즘 문제/BOJ

17485번 진우의 달 여행 (Large)

parkit 2021. 3. 20. 20:25
728x90
반응형

www.acmicpc.net/problem/17485

 

17485번: 진우의 달 여행 (Large)

첫줄에 지구와 달 사이 공간을 나타내는 행렬의 크기를 나타내는 N, M (2 ≤ N, M ≤ 1000)이 주어진다. 다음 N줄 동안 각 행렬의 원소 값이 주어진다. 각 행렬의 원소값은 100 이하의 자연수이다.

www.acmicpc.net

 

 

 

 

 

맞은 문제이지만, 이상하게 다른 정답 코드들보다 긴 것 같았다.

(아래는 내 코드이고, 맨 아래 코드가 정답자 분의 코드를 참고하여 다시 구현한 코드이다.)

#include <bits/stdc++.h>

using namespace std;

#define MAX 1010

int m[MAX][MAX], R, C;
int dp[MAX][MAX][3];

int main(void)
{
	cin.tie(0);

	int answer = INT32_MAX;

	scanf("%d %d", &R, &C);

	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {		
			scanf("%d", &m[i][j]);
			if (i == 0) {
				dp[i][j][0] = dp[i][j][1] = dp[i][j][2] = m[i][j];
			}	
		}
	}

	// 0 : ↙, 1 : ↓, 2 : ↘
	for (int i = 1; i < R; i++) {
		for (int j = 0; j < C; j++) {
			if (j == 0) {
				dp[i][j][1] += dp[i - 1][j + 1][0] + m[i][j]; // ↙에서 ↓
				dp[i][j][2] += dp[i - 1][j + 1][0] + m[i][j]; // ↙에서 ↘

				dp[i][j][2] = dp[i][j][2] == 0 ? dp[i - 1][j][1] + m[i][j] : min(dp[i][j][2], dp[i - 1][j][1] + m[i][j]); // ↓에서 ↘
			}
			else if (j == C - 1) {
				dp[i][j][1] += dp[i - 1][j - 1][2] + m[i][j]; // ↘에서 ↓
				dp[i][j][0] += dp[i - 1][j][1] + m[i][j]; // ↓에서 ↙

				dp[i][j][0] = dp[i][j][0] == 0 ? dp[i - 1][j - 1][2] + m[i][j] : min(dp[i][j][0], dp[i - 1][j - 1][2] + m[i][j]); // ↘에서 ↙
			}
			else {
				dp[i][j][0] += dp[i - 1][j - 1][2] + m[i][j]; // ↘에서 ↙
				dp[i][j][1] += dp[i - 1][j - 1][2] + m[i][j]; // ↘에서 ↓
				dp[i][j][2] += dp[i - 1][j][1] + m[i][j]; // ↓에서 ↘

				dp[i][j][0] = dp[i][j][0] == 0 ? dp[i - 1][j][1] + m[i][j] : min(dp[i][j][0], dp[i - 1][j][1] + m[i][j]); // ↓에서 ↙
				dp[i][j][1] = dp[i][j][1] == 0 ? dp[i - 1][j + 1][0] + m[i][j] : min(dp[i][j][1], dp[i - 1][j + 1][0] + m[i][j]); // ↙에서 ↓
				dp[i][j][2] = dp[i][j][2] == 0 ? dp[i - 1][j + 1][0] + m[i][j] : min(dp[i][j][2], dp[i - 1][j + 1][0] + m[i][j]); // ↙에서 ↘
			}
		}
	}

	for (int j = 0; j < C; j++) {
		for (int k = 0; k < 3; k++) {
			if (dp[R - 1][j][k] == 0) {
				continue;
			}
			//printf("dp[%d][%d][%d] = %d\n", R - 1, j, k, dp[R - 1][j][k]);
			answer = min(answer, dp[R - 1][j][k]);
		}
	}

	printf("%d\n", answer);

	return 0;
}

 

 

 

 

 

 

아래는 정답자 분들 중에서의 코드를 참고하여 다시 작성해본 코드이다.

 

#include <bits/stdc++.h>

using namespace std;

#define MAX 1010
#define INF 2e9

int m[MAX][MAX], R, C;
int dp[MAX][MAX][3];

int getMinDistance(int r, int c, int d)
{
	if (c < 0 || c >= C) return INF;
	if (d == 0) return min(dp[r][c][1], dp[r][c][2]);
	if (d == 1) return min(dp[r][c][0], dp[r][c][2]);
	return min(dp[r][c][0], dp[r][c][1]);
}

int main(void)
{
	cin.tie(0);

	int answer = INT32_MAX;

	scanf("%d %d", &R, &C);

	for (int i = 0; i < R; i++) {
		for (int j = 0; j < C; j++) {		
			scanf("%d", &m[i][j]);
			if (i == 0) {
				dp[i][j][0] = dp[i][j][1] = dp[i][j][2] = m[i][j];
			}	
		}
	}

	// 0 : ↙, 1 : ↓, 2 : ↘
	for (int i = 1; i < R; i++) {
		for (int j = 0; j < C; j++) {
			for (int k = 0; k < 3; k++) {
				dp[i][j][k] = getMinDistance(i - 1, j - 1 + k, k) + m[i][j];
			}
		}
	}

	for (int j = 0; j < C; j++) {
		for (int k = 0; k < 3; k++) {
			//printf("dp[%d][%d][%d] = %d\n", R - 1, j, k, dp[R - 1][j][k]);
			answer = min(answer, dp[R - 1][j][k]);
		}
	}

	printf("%d\n", answer);

	return 0;
}
728x90
반응형

'알고리즘 문제 > BOJ' 카테고리의 다른 글

13908번 비밀번호  (0) 2021.04.06
14391번 종이 조각  (0) 2021.04.01
1562번 계단수  (0) 2021.03.08
19237번 어른상어  (0) 2021.02.13
20055번 컨베이어 벨트 위의 로봇  (0) 2020.11.15