[적용한 알고리즘]
DP
[아이디어]
1번과 N번이 둘 다 색칠되는 경우를 제외하고는, 나머지 경우는 선형으로 생각해줘도 된다.
dp[N][K] = N 개 짜리 색상환을 중 K 개를 인접하지 않게 칠하는 경우의 수
두 가지 경우로 나눌 수 있는데,
현재 i 번째 칸을 보고 있고
j 개의 칸을 칠했다고 하면,
1. i 번째 칸을 칠하는 경우 = dp[i - 2][j - 1]
2. 안칠하는 경우 = dp[i - 1][j]
이므로, dp[i][j] = dp[i - 2][j - 1] + dp[i - 1][j] 다
이때 문제가 되는게 dp[n][k] 인데,
dp[n][k] 면
1. N번째 칸을 칠하는 경우
1 번 칸을 칠해서는 안되고, N - 1번 칸도 칠하면 안되므로,
2 ~ N - 1 까지의 칸을 K - 1개의 색을 인접하지 않게 칠하는 경우와 같으므로,
dp[N-3][K - 1] 개이다
2. N번째 칸을 칠하지 않는 경우
1 ~ N - 1 까지 K 개의 색을 인접하지 않게 칠하는 경우와 같으므로,
dp[N - 1][K] 이다
따라서, dp[N][K] = dp[N - 3][K - 1] + dp[N - 1][K] 으로 구할 수 있다.
[교훈]
오랜만에 재밌는 확통 문제 푼 느낌이다.
<코드>
#include <cstdio>
#include <algorithm>
using namespace std;
const int mod = 1000000003;
int dp[1001][1001];
int N, K;
int main(){
scanf("%d %d", &N, &K);
for (int i = 0; i <= N; i++){
dp[i][1] = i;
dp[i][0] = 1;
}
for (int i = 2; i <= N; i++){
for (int j = 2; j <= K; j++){
dp[i][j] = (dp[i - 2][j - 1] + dp[i - 1][j]) % mod;
}
}
int ans = (dp[N - 1][K] + dp[N - 3][K - 1]) % mod;
printf("%d\n", ans);
return 0;
}
'Algorithm > BOJ' 카테고리의 다른 글
[백준] 1412번 일방통행 (124) | 2020.02.01 |
---|---|
[백준] 1922번 네트워크 연결 (0) | 2020.01.10 |
[백준] 9084번 동전 (0) | 2020.01.10 |
[백준] 9507번 Generations of Tribbles (121) | 2020.01.10 |
[백준] 2240번 자두나무 (0) | 2020.01.10 |