본문 바로가기

Algorithm/Back Tracking

BaekJoon 2661 좋은수열

Link https://www.acmicpc.net/problem/2661

소스결과 1988 KB / 0 ms

출처 Baekjoon, KOI 1997

언어 C++ 17

분류 수학, 백트래킹

 

설명

1, 2, 3으로 이루어진 수열 중 인접한 두개의 부분 수열이 동일한 하지 않은 최솟값 수열을 출력하는 문제이다.

 

첫 자리를 제외하고 나머지 자리는 2번씩 검색해야하는 느낌이 드는 문제이다. 시간 제한이 1초인 점이 의심스럽다.

하지만 위 문제는 간단히 생각하면 앞자리가 1인 경우가 항상 최소가 되는 수열이다.

수열을 검사하는 부분을 최대한 간략화 시키기만 한다면 쉽게 문제가 풀린다.

 

알고리즘

1. 수를 입력받는다.

2. 현재 위치의 문자 값을 1 ~ 3 사이로 설정한다.

 2 - 1. 0번 인덱스를 제외한 나머지 부분에서 문자를 설정하는 경우 현재까지 입력된 문자열에 대해서 좋은수열인지 판별한다.

 2 - 2. 현재 문자를 넣은 후 좋은 수열이라고 판별이 되면 다음 위치로 이동후 2번 함수를 반복한다.

 2 - 3. 목표 위치에 도달하는 경우 모든 함수를 종료시킨다.

3. 문자열을 출력후 종료한다.

 

좋은 수열 판별 함수.

1. 검사할 문자열 길이를 1 부터 문자열 길이의 절반까지 반복한다.

 1 - 1. 문자열 길이만큼 대칭 구조로 검사한다. 중복이 되지 않는 경우를 발견시 반복을 종료 후 검사할 문자열 길이를 1 늘이는 것을 반복한다.

 1 - 2. 수열이 반복되는 경우가 발견되면 false를 반환한다.

 

소스코드

#include <iostream>

using namespace std;

const short MAX = 80;
char number[MAX + 1] = {};
int n;

bool isAble(int pos)
{
	for (int i = 1; i <= (pos + 1) / 2; i++)
	{
		bool duple = false;
		for (int j = 0; j < i; j++)
		{
			if (number[pos - j] != number[pos - i - j]) {
				duple = duple | true;
				break;
			}
		}

		if (!duple)
			return false;
	}
	return true;
}

int solution(int pos)
{
	if (pos == n)
	{
		return 0;
	}
	else
	{
		for (int i = '1'; i < '1' + 3; i++)
		{
			number[pos] = i;
			if (isAble(pos))
			{
				int res = solution(pos + 1);
				if (res != -1)
					return res;
			}
		}
	}

	return -1;
}

int main()
{
	cin >> n;

	solution(0);
	
	cout << number;

	return 0;
}

 

'Algorithm > Back Tracking' 카테고리의 다른 글

BaekJoon 1339 단어 수학  (0) 2019.02.08
BaekJoon 1342 행운의 문자열  (0) 2019.02.08
BaekJoon 2580 스도쿠  (0) 2019.01.11
BaekJoon 1759 암호만들기  (0) 2019.01.11
BaekJoon 9663 N-Queens  (0) 2018.12.31