ABC (BOJ 12969)
2024. 8. 26. 19:47ㆍBOJ/DP
문제
문제 설명
- 문자열 s는 'A', 'B', "C'로 이루어져 있고 크기순서는 A <B <C순서이다.
- 0보다 크고 N보다 작은 i, j( i <j )가 있다고 할 때 s [i]<s [j]를 만족하는 개수가 총 K개가 되어야 한다.
- 단 여러 개가 존재할 경우에는 아무거나 출력해도 되고 A, B, C가 모두 포함될 필요는 없다.
문제 해설
- 동적 계획법: A의 개수, B의 개수, C의 개수, 모든 알파벳의 개수로 나누어서 재귀함수를 통해서 문자열을 만들어 나간다.
최종 코드
#include <iostream>
using namespace std;
int n, k;
int dp[31][31][31][504];
bool f(int x, int y, int z, int sum, string s) {
if (x + y + z == n) { #알파벳의 총 개수가 n일떼
if (sum == k) {
cout << s;
return 1;
}
return 0;
}
if (dp[x][y][z][sum] != -1) return 0;
dp[x][y][z][sum] = 0;
if (f(x + 1, y, z, sum, s + 'A')) return 1;
if (f(x, y + 1, z, sum + x, s + 'B')) return 1;
if (f(x, y, z + 1, sum + x + y, s + 'C')) return 1;
return 0;
}
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin >> n >> k;
for (int i = 0; i <= n; i++) { #-1로 dp 배열 초기화하기
for (int j = 0; j <= n; j++) {
for (int l = 0; l <= n; l++) {
for (int m = 0; m <= 503; m++) {
dp[i][j][l][m] = -1;
}
}
}
}
if (!f(0, 0, 0, 0, "")) cout << -1;
}
- x: A의 개수
- y: B의 개수
- z: C의 개수
- sum: s [i]<s [j] ( 0 ≤ i < j < N )인 쌍들의 개수를 저장
if (f(x + 1, y, z, sum, s + 'A')) return 1;
if (f(x, y + 1, z, sum + x, s + 'B')) return 1;
if (f(x, y, z + 1, sum + x + y, s + 'C')) return 1;
- 만약 A가 들어오게 된다면 A보다 큰 알파벳은 없기 때문에 sum을 그대로 보낸다.
- 만약 B가 들어오게 된다면 B보다 작은 알파벳은 A이기 때문에 A의 개수 x를 sum에 더해준다.
- 만약 C가 들어오게 된다면 C보다 작은 나머지 알파벳의 개수를 sum에 더해준다.
if (x + y + z == n) {
if (sum == k) {
cout << s;
return 1;
}
return 0;
}
- x+y+z, 즉 모든 알파벳의 개수가 n이 되고 sum이 k와 같다면 알파벳 문자열을 출력해 준다.
'BOJ > DP' 카테고리의 다른 글
| 성인 게임 (BOJ 23256) (2) | 2024.11.24 |
|---|---|
| 할로윈의 양아치(BOJ20303) (1) | 2024.11.17 |
| 암호코드 (BOJ 2011) (2) | 2024.10.09 |
| 올바른 괄호 문자열 (BOJ 3012) (1) | 2024.09.12 |
| 평범한 배낭(BOJ 12865번) (0) | 2024.05.02 |

