728x90
문제
https://www.acmicpc.net/problem/2661
사용한 알고리즘
2022.01.29 - [PS/Algorithm] - [알고리즘 개념정리] 6. 완전탐색/백트래킹
-> 백트래킹.
모든 경우에 대해 따져주지 않아도 되는 가지치기 문제
풀이
나쁜 수열에는 마지막에 어떤 숫자를 추가하더라도 나쁜 수열이다.
따라서 우리는 좋은 수열들에 대해서만 추가적으로 숫자를 붙여가며 좋은 수열인지 테스트하면 된다.
*solve함수
- 지금까지 만든 수열이 좋은 수열일 때만 숫자 하나를 붙여서 재귀함수를 수행한다.
이때, 좋은 수열인지 판단하기 위해서는 check함수를 사용하였다. - 만든 수열의 길이가 n이 되면 그 수열을 출력 후 종료한다.
*check함수
현재 인덱스까지 좋은 수열이면 1을, 나쁜 수열이면 0을 반환하는 함수이다.
아래 수열 ans를 예로 들어보자.
idx | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
ans | 1 | 2 | 3 | 2 | 1 | 2 | 3 |
반복문을 돌면서 뒤쪽부터 비교해준다.
i=1일 때 (인접한 길이 1의 부분 수열이 동일한지)
ans[6]==ans[5] ? 을 확인하고
i=2일 때 (인접한 길이 2의 부분 수열이 동일한지)
ans[6]==ans[4] && ans[5]==ans[3] ? 을 확인하고
i=3일 때 (인접한 길이 3의 부분 수열이 동일한지)
ans[6]==ans[3] && ans[5]==ans[2] && ans[4]==ans[1] ? 을 확인한다.
i=1부터 (idx+1)/2까지 전부 확인하였는데 동일한 부분 수열이 없었다면 1을 반환하면 된다.
소스코드
#include <iostream>
typedef long long ll;
using namespace std;
int ans[81];
int n;
int check(int idx){
//현재 인덱스까지 좋은 수열이면 1을, 나쁜 수열이면 0을 반환하는 함수이다.
//맨뒤부터 연속한 한글자가 같은지 두글자가 같은지...반반 같은지//를 체크한다.
for(int i=1; i<=(idx+1)/2; i++){
int same=1;
for(int j=idx; j>idx-i; j--){
if(ans[j]!=ans[j-i]){
same=0;
break;
}
}
if(same) return 0;
}
return 1;
}
void solve(int idx){
// 만든 수열의 길이가 n이 되면 그 수열을 출력 후 종료한다.
if(idx==n){
for(int i=0; i<n; i++) cout<<ans[i];
exit(0);
}
for(int i=1; i<=3; i++){
ans[idx]=i;
if(check(idx)) // 지금까지 만든 수열이 좋은 수열일때만 숫자하나를 붙여서 재귀함수를 수행한다.
solve(idx+1);
else continue;
}
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
cin>>n;
solve(0);
return 0;
}
728x90
'PS > Baekjoon' 카테고리의 다른 글
[백준/C++] 2370번: 시장 선거 포스터(G4) (0) | 2022.02.03 |
---|---|
[백준/C++] 17136번: 색종이 붙이기(G2) (0) | 2022.01.31 |
[백준/C++] 1182번: 부분수열의 합(S2) (0) | 2022.01.30 |
[백준/C++] 15650번: N과 M (2)(S3) (0) | 2022.01.30 |
[백준/C++] 1747번: 소수&팰린드롬(S1) (0) | 2022.01.29 |
댓글