https://www.acmicpc.net/problem/10942
10942번: 팰린드롬?
총 M개의 줄에 걸쳐 홍준이의 질문에 대한 명우의 답을 입력으로 주어진 순서에 따라서 출력한다. 팰린드롬인 경우에는 1, 아닌 경우에는 0을 출력한다.
www.acmicpc.net
EXPLANATION
수열이 팰린드롬이려면,
양끝이 같고 그 사이가 팰린드롬이면 된다.
수열의 길이가 1일 때는 숫자 하나 그 자체로 양끝이나 그 사이가 존재하지 않고,
수열의 길이가 2일 때는 양끝이 존재하지만, 그 사이가 존재하지 않는다.
따라서, 따로 미리 설정을 해야한다. (base)
수열의 길이가 1일 때는 그 자체로 팰린드롬이다.
수열의 길이가 2일 때는 2 숫자가 같으면 팰린드롬이다.
수열의 길이가 작은 거부터 확인해야,
이후에 더 큰 길이의 수열이 팰린드롬인 지 구할 때,
그 수열의 양끝 사이에 있는 수열을 이용할 수 있다.
for (int i = 2; i <= N - 1; i++) { //수열의 길이 3부터 N까지. j~j+2: 3개, j~j+(N - 1): N개
for (int j = 1; j <= N - i; j++) { //j+i의 최대는 N.
//앞 뒤 사이에 있는 수들이 팰린드롬이면 팰린드롬.
if (arr[j] == arr[j + i] && palindrom[j + 1][j + i - 1] == true) {
palindrom[j][j + i] = true;
}
}
}
혹은,
for (int i = N - 2; i >= 1; i--) {
for (int j = i + 2; j <= N; j++) {
if (arr[i] == arr[j] && palindrom[i + 1][j - 1] == true) {
palindrom[i][j] = true;
}
}
}
이렇게 해도 된다.
예를 들어 설명하겠다.
1 2 1 3 1 2 1
위와 같은 수열이 이루어졌을 때, 팰린드롬을 이루는 경우를 표로 나타내보자.
palindrom이 true면 O, false면 X.
| 테스트 케이스 | 1 | 2 | 1 | 3 | 1 | 2 | 1 | |
| palindrom | [1] | [2] | [3] | [4] | [5] | [6] | [7] | |
| [1] | O | X | O | X | X | X | O | |
| [2] | O | X | X | X | O | X | ||
| [3] | O | X | O | X | X | |||
| [4] | O | X | X | X | ||||
| [5] | O | X | O | |||||
| [6] | O | X | ||||||
| [7] | O | |||||||
이렇게 보면 어디서부터 DP를 시작해야 할지 볼 수 있다.
if (arr[i] == arr[j] && palindrom[i + 1][j - 1] == true) palindrom[i][j] = true;이므로,
palindrom[s][e]를 확인하려면, palindrom[s + 1][e -1]을 알아야 한다.
그러면 dp는 가장 밑에서 부터 위로, 왼쪽에서부터 오른쪽으로 채워져야 한다.
그런데, 길이가 1, 2일 때인 palindrom[i][i], palindrom[i][i+1]은 이미 확인했으므로,
i= N - 2부터 1까지 1칸씩 내려오면 되고,
j = i+2부터 N까지 1칸씩 오른쪽으로 가면딘다.
그걸 표현한 것이 위의 2번째 코드.
CODE
#include <iostream>
using namespace std;
int arr[2001];
bool palindrom[2001][2001] = { false };
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int N;
cin >> N;
for (int i = 1; i <= N; i++) {
cin >> arr[i];
//길이가 1일 때는 무조건 팰린드롬.
palindrom[i][i] = true;
//길이가 2일 때, 2 수가 같으면 팰린드롬.
if (arr[i-1] == arr[i])
palindrom[i-1][i] = true;
}
//길이가 3이상 일 때, 앞 뒤가 같고, 앞 뒤 사이에 있는 수들이 팰린드롬이면 팰린드롬.
for (int i = N - 2; i >= 1; i--) {
for (int j = i + 2; j <= N; j++) {
if (arr[i] == arr[j] && palindrom[i + 1][j - 1] == true) {
palindrom[i][j] = true;
}
}
}
int M, S, E;
cin >> M;
for (int i = 0; i < M; i++) {
cin >> S >> E;
cout << palindrom[S][E] << '\n';
}
return 0;
}

'백준BOJ > 동적 계획법' 카테고리의 다른 글
| 백준 2293 동전 1 (0) | 2022.06.26 |
|---|---|
| 백준 2629 양팔저울 (0) | 2022.06.26 |
| 백준 1520 내리막길 (0) | 2022.06.25 |
| 백준 11049 행렬 곱셈 순서 (0) | 2022.06.25 |
| 백준 11066 파일 합치기 (0) | 2022.06.25 |
댓글