[적용한 알고리즘]
DP
[아이디어]
DP[지난 시간][이동한 횟수][현재 있는 나무]
그리고 자두가 떨어지는 위치를 입력한 배열을 a[] 라고 했을 때,
현재 시간을 i,
움직인 횟수를 j,
현재 있는 나무가 1번 혹은 2번 이면,
1. a[i] = 1 인 경우
1-1) 1번 나무에 위치한 경우 (받아먹는 경우)
dp[i][j][1] = max(받아먹기 위해 2번에서 이동한 경우, 그대로 1번에 있던 경우) + 1
102) 2번 나무에 위치한 경우 (이번엔 받아먹지 않기로 한 경우)
dp[i][j][2] = dp[i - 1][j][2]
2. a[i] = 2 인 경우
2-1) 2번 나무에 위치한 경우 (받아먹는 경우)
dp[i][j][2] = max(받아먹기 위해 1번에서 이동한 경우, 그대로 1번에 있던 경우) + 1
2-2) 1번 나무에 위치한 경우 (이번엔 받아먹지 않기로 한 경우)
dp[i][j][1] = dp[i - 1][j][1]
[교훈]
여기서 반드시 신경 써줘야하는 경우가 j = 0 (한번도 안움직이는 경우) 이다.
j - 1 이 음수가 되는 경우를 (j = 0) 신경안써주고 코드 썼다가 피똥쌌다.
j = 0 인 경우도 분류 해줘야한다.
찾는데 한참 걸렸다..
<코드>
#include <cstdio>
#include <algorithm>
using namespace std;
int main(){
int T, W;
scanf("%d %d", &T, &W);
int a[1001];
for (int i = 1; i <= T; i++){
scanf("%d", &a[i]);
}
int dp[1001][31][3] = { 0 };
if (a[1] == 1) dp[1][0][1] = 1;
if (a[1] == 2) dp[1][1][2] = 1;
for (int i = 2; i <= T; i++){
for (int j = 0; j <= W; j++){
if (a[i] == 1){
if (j == 0){
dp[i][0][1] = dp[i - 1][0][1] + 1;
continue;
}
dp[i][j][1] = max(dp[i - 1][j][1], dp[i - 1][j - 1][2]) + 1;
dp[i][j][2] = dp[i - 1][j][2];
}
if (a[i] == 2){
if (j == 0){
dp[i][0][1] = dp[i - 1][0][1];
continue;
}
dp[i][j][1] = dp[i - 1][j][1];
dp[i][j][2] = max(dp[i - 1][j - 1][1], dp[i - 1][j][2]) + 1;
}
}
}
int ans = -1;
for (int i = 0; i <= W; i++){
ans = max(ans, max(dp[T][i][1], dp[T][i][2]));
}
printf("%d", ans);
return 0;
}
'Algorithm > BOJ' 카테고리의 다른 글
[백준] 9084번 동전 (0) | 2020.01.10 |
---|---|
[백준] 9507번 Generations of Tribbles (121) | 2020.01.10 |
[백준] 1390번 테트리스 (128) | 2020.01.07 |
[백준] 1351번 무한 수열 (0) | 2020.01.01 |
[백준] 5557번 1학년 (0) | 2020.01.01 |