색상환 (BOJ 2482)
2025. 2. 2. 19:49ㆍBOJ
문제
문제 설명
- n개의 색들이 주어지는 데 인접한 색을 동시에 사용하지 않을 려고 한다.
- K개의 색을 뽑는 경우의 수를 구해야 한다.
최종 코드
#include<bits/stdc++.h>
#define MOD 1000000003
using namespace std;
int n, k;
long long dp[1004][1004];
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> n >> k;
if (n < k * 2) {
cout << 0;
return 0;
}
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
dp[i][1] = i;
//0개를 뽑는 경우는 1가지
//1개를 뽑는 경우는 i가지
}
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;
//dp[i - 2][j - 1]: 현제 색을 선택하는 경우
//dp[i-1][j]: 현제 색을 선택하지 않고 넘어가는 경우
}
}
cout << (dp[n - 1][k] + dp[n - 3][k - 1]) % MOD;
//dp[n - 1][k]: 첫번째 색을 선택하는 경우
//dp[n-3][j-1]: 첫번째 색을 선택하지 않는 경우
}
문제 해설
dp[a][b]
a: 색의 개수
b: 색을 뽑는 개수dp[i][j] = (dp[i - 2][j - 1] + dp[i - 1][j]) % MOD;
색을 뽑을 때 인접한 색을 뽑을 수 없기 때문에 두 가지의 경우로 나누어 봐야 한다.
1. 현제 색을 선택하는 경우: dp [i - 2][j - 1]
- i번 째 색을 선택하기 위해서는 i-1번째가 아니라 i-2번째 색까지의 경우를 선택해야 한다.
2. 현제 색을 선택하지 않는 경우: dp [i-1][j]
-i-1번째 색까지 탐색한 경우 중에서 j개를 뽑은 경우를 선택해줘야 한다.cout << (dp[n - 1][k] + dp[n - 3][k - 1]) % MOD;
여기에서 나오는 경우는 원형이기 때문에 dp [n][k]를 출력해 주면 안 된다.
그렇기에 첫 번째 색을 선택하는 경우와 선택하지 않는 경우로 나누어 줘야 한다.
1. 첫 번째를 선택하지 않는 경우: dp [n - 1][k]
-이 경우는 첫 번째만 제외한 n-1개의 경우를 찾아주면 된다.
2. 첫 번째를 선택하는 경우: dp [n - 3][k - 1]
-첫 번째 색을 뽑고 양옆을 사용할 수 없다고 가정하면 n-3개 중에서 j-1개를 뽑는 경우를 찾아주면 된다.
'BOJ' 카테고리의 다른 글
| 알파벳과 쿼리 (Hard) (BOJ 31830) (0) | 2025.03.09 |
|---|---|
| 소수 수열 (BOJ 31827) (0) | 2025.03.09 |
| 맛있는 사과 (BOJ 32963) (0) | 2025.01.28 |
| XOR (BOJ 14245) (0) | 2025.01.14 |
| Ignition(점화) (BOJ 13141) (1) | 2024.08.08 |

