Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- OS
- 네트워크
- 자바
- back-end
- kotlin
- 모던자바
- java
- 백준
- DP
- lambda
- Brute-force
- baekjoon
- LEVEL2
- algorithm
- 스프링
- backtracking
- TDD
- 알고리즘
- BFS
- DFS
- 자료구조
- 운영체제
- 프로젝트
- 백트래킹
- Java8
- 그래프
- programmers
- 프로그래머스
- Spring
- 코틀린
Archives
- Today
- Total
요깨비's LAB
[프로그래머스, JAVA] 땅따먹기 본문
[ 문제 ]
땅따먹기 게임을 하려고 합니다.
땅따먹기 게임의 땅(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 이하의 자연수
입출력 예
land [[1,2,3,5],[5,6,7,8],[4,3,2,1]]
answer 16
간단한 문제로 생각해서 풀었는데... Test Case는 맞았지만 나머지는 모두 틀려서 0점...
그 이유는 현재 땅 중 방문하지 않았으며 그중에서 가장 큰 땅을 선택하는 Greedy 방식으로 풀어서 전부 틀렸습니다.. (접근 자체가 FAIL)
<Greedy>
// 기존 실패 코드 Greedy 방식
class Solution {
boolean[] visited = new boolean[4];
int result = 0;
int col;
int solution(int[][] land) {
col = land.length;
getMaxInNotVisitedPrevRow(land, 0, -1);
return result;
}
public void getMaxInNotVisitedPrevRow(int[][] land, int colNum, int prevMaxIdx) {
if (colNum == col)
return;
int idx = 0;
int max = Integer.MIN_VALUE;
if (colNum == 0) {
for (int i = 0; i < 4; i++) {
if (max < land[0][i]) {
max = land[0][i];
idx = i;
}
}
visited[idx] = true;
} else {
for (int i = 0; i < 4; i++) {
if (!visited[i] && max < land[colNum][i]) {
max = land[colNum][i];
idx = i;
}
}
visited[prevMaxIdx] = false;
visited[idx] = true;
}
result += max;
getMaxInNotVisitedPrevRow(land, colNum + 1, idx);
}
}
이후에 DP를 이용해서 매 단계마다 가장 큰 값이 아닌 이전의 방문 경로 중 현재 방문 위치와 겹치지 않으면서 가장 큰 값을 선택하는
방식으로 바꿨습니다.
<DP>
class Solution {
int[][] dp;
int[][] map;
// boolean[] visited = new boolean[4];
int solution(int[][] land) {
int answer = 0;
dp = new int[land.length][land[0].length];
map = land;
int col = dp.length;
int row = dp[0].length;
for (int i = 0; i < col; i++) {
for (int j = 0; j < row; j++) {
dp[i][j] = map[i][j];
}
}
for (int i = 0; i < 4; i++) {
calculate(1);
}
// for (int i = 0; i < col; i++) {
// for (int j = 0; j < row; j++) {
// System.out.print(dp[i][j] + " ");
// }
// System.out.println();
// }
int max = Integer.MIN_VALUE;
for (int i = 0; i < 4; i++) {
if (max < dp[col - 1][i])
max = dp[col - 1][i];
}
return max;
}
void calculate(int colNum) {
// int idx = -1;
if (colNum >= dp.length) {
return;
}
for (int i = 0; i < 4; i++) {
for(int j=0;j<4;j++) {
if(i == j)
continue;
if (dp[colNum][i] < map[colNum][i] + dp[colNum - 1][j]) {
// idx = i;
dp[colNum][i] = map[colNum][i] + dp[colNum - 1][j];
}
}
// dp[colNum][i] = Math.max(dp[colNum][i],map[colNum][i] +
// map[colNum-1][prevIndex]);
}
calculate(colNum + 1);
}
}
바로 Greedy를 떠올리다니... 조금 더 숙고하고 생각했으면 혹시라도 DP를 먼저 떠올렸을 수도 있었을 텐데요 심지어
간단한 DP일 뿐인데도 머리 쥐어짜면서 짰습니다.. 열심히 하겠습니다.. 빛이 보이는 날까지
'알고리즘(Java) > 프로그래머스' 카테고리의 다른 글
[프로그래머스, JAVA] 저울 (0) | 2020.02.12 |
---|---|
[프로그래머스, JAVA] 피보나치 수 (0) | 2019.12.23 |
[프로그래머스, JAVA] 올바른 괄호 (0) | 2019.12.13 |
[프로그래머스, JAVA] 다음 큰 숫자 (0) | 2019.12.13 |
[프로그래머스, JAVA, 다시풀어보기] 가장 큰 정사각형 찾기 (0) | 2019.12.07 |
Comments