좋은수열
https://www.acmicpc.net/problem/2661
| 시간 제한 | 메모리 제한 | 제출 | 정답 | 맞힌 사람 | 정답 비율 |
|---|---|---|---|---|---|
| 1 초 | 128 MB | 11169 | 5455 | 4188 | 50.144% |
문제
숫자 1, 2, 3으로만 이루어지는 수열이 있다.
임의의 길이의 인접한 두 개의 부분 수열이 동일한 것이 있으면, 그 수열을 나쁜 수열이라고 부른다.
그렇지 않은 수열은 좋은 수열이다.
다음은 나쁜 수열의 예이다.
- 33
- 32121323
- 123123213
다음은 좋은 수열의 예이다.
- 2
- 32
- 32123
- 1232123
길이가 N인 좋은 수열 들을 N자리의 정수로 보아 그 중 가장 작은 수를 나타내는
수열을 구하는 프로그램을 작성하라.
예를 들면, 1213121과 2123212는 모두 좋은 수열이지만
그 중에서 작은 수를 나타내는 수열은 1213121이다.
입력
입력은 숫자 N하나로 이루어진다. N은 1 이상 80 이하이다.
출력
첫 번째 줄에 1, 2, 3으로만 이루어져 있는 길이가 N인 좋은 수열 들 중에서 가장 작은 수를
나타내는 수열만 출력한다.
수열을 이루는 1, 2, 3 들 사이에는 빈칸을 두지 않는다.
예제 입력 1
7
예제 출력 1
1213121
출처
Olympiad > 한국정보올림피아드 > KOI 1997 > 중등부 1번
알고리즘 분류
1차 시도
BFS로 모든 경우를 다 만들어 놓고 시작하려니 N이 80 이 되는 순간 프로그램이 나락을 간다.
실패코드
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
queue<pair<int,int>> myQueue;
int N;
void BFS(int N)
{
myQueue.push({0, N});
while (!myQueue.empty())
{
int x = myQueue.front().first;
int n = myQueue.front().second;
myQueue.pop();
cout << n << " \n";
if (n == 0)
{
//cout << x << " \n";
continue;
}
for (int i = 1; i <= 3; i++)
{
if (i == 1)
{
myQueue.push({ x + 1 * pow(10, n - 1), n-1 });
}
else if (i == 2)
{
myQueue.push({ x + 2 * pow(10, n - 1), n - 1 });
}
else if (i == 3)
{
myQueue.push({ x + 3 * pow(10, n - 1), n - 1 });
}
}
}
}
int main()
{
cin >> N;
BFS(N);
return 0;
}
계산 중 깊이를 측정해보니 이건 노답 이라는 것을 깨달았다.

DFS로 변경
목표는 가장 낮은 숫자를 찾는 것 => 1부터 시작해서 탐색
#include <iostream>
#include <queue>
#include <cmath>
using namespace std;
int N;
void DFS(int n, int value)
{
if (n == 0)
{
cout << value << "\n";
return;
}
for (int i = 1; i <= 3; i++)
{
if (i == 1)
{
DFS(n - 1, value + 1 * pow(10, n - 1));
}
else if (i == 2)
{
DFS(n - 1, value + 2 * pow(10, n - 1));
}
else if (i == 3)
{
DFS(n -1, value + 3 * pow(10, n - 1));
}
}
}
int main()
{
cin >> N;
DFS(N, 0);
cout << "end";
return 0;
}
N은 80까지 가능
80 자리…
string 으로 변환….

#include <iostream>
#include <string>
using namespace std;
int N;
void DFS(int n, string value)
{
if (n == 0)
{
cout << value << "\n";
return;
}
for (int i = 1; i <= 3; i++)
{
if (i == 1)
{
DFS(n - 1, value + '1');
}
else if (i == 2)
{
DFS(n - 1, value + '2');
}
else if (i == 3)
{
DFS(n - 1, value + '3');
}
}
}
int main()
{
cin >> N;
DFS(N, "");
cout << "end";
return 0;
}

조건에 부합하는 가장 처음 값이 정답
성공 코드(DFS)
#include <iostream>
#include <string>
using namespace std;
int N;
string number;
void DFS(char ch, int cnt)
{
// 제일 먼저 조건에 부합하는 숫자가 답
if (cnt - 1 == N) {
cout << number;
exit(0);
}
number += ch;
for (int i = 1; i <= cnt/2; i++)
{
string a = number.substr(cnt - i, i);
string b = number.substr(cnt - i * 2, i);
if (a == b){
// 나쁜 수열이면 지우고 리턴
number.erase(cnt - 1);
return;
}
}
for (int i = 1; i <= 3; i++)
{
DFS(i + '0', cnt + 1);
}
// cnt - 1 자리가 성립하지 않을 경우
number.erase(cnt - 1);
}
int main()
{
cin >> N;
for (int i = 1; i <= 3; i++)
{
// '0' 에서 i 만큼 더하면 i
DFS(i + '0', 1);
}
return 0;
}


![백준 1110번 (더하기 사이클, C++) [BAEKJOON]](https://lycos7560.com/wp-content/uploads/boj-og.png)
![백준 11559번 (Puyo Puyo, C++) / 추가 반례 [BAEKJOON]](https://lycos7560.com/wp-content/uploads/boj-og-1.png)