BOJ 2505 두 번 뒤집기


사용한 알고리즘

  • 구현

알고리즘 설명

  • 몇가지 예외처리를 진행한 뒤, 뒤집기를 진행한다.
  • Case1. 안 뒤집어도 되는 경우, (1 1), (1 1)로 하나만 뒤집어 끝낸다
  • Case2. 한번만 뒤집어도 되는 경우, (뒤집을 좌표),(1 1)를 출력
  • Case3. 두번 뒤집어야 하는 경우, 둘다 출력한다
  • 위 알고리즘에서 뒤집는 형태가 앞에서 부터 맞지 않는 부분을 찾아서 풀어나가는 형태와 뒤에서부터 맞지 않는 부분을 찾아서 풀어가는 형태가 있다.
  • 두번 뒤집는 경우, 앞에서 부터 뒤집었던 경우 또는 위에서 부터 뒤집는 경우 2가지만 있으므로 이것만 확인하면 된다.

풀이

// baekjoon 2505 yechan
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAX_N=10002;

int N, step[MAX_N], s, e, ans[2][2];

int main() {
	scanf("%d", &N);
	for (int i=1; i<=N; ++i)
		scanf("%d", &step[i]);

// 앞에서 부터 어디까지 정렬되어 있는지 확인
	s=1;
	while (s <= N && step[s] == s) s++;
	if (s == N+1) return !printf("1 1\n1 1\n");

// 정렬되지 않은 부분의 숫자가 어디에 있는지 찾아 e에 저장한다.
	e=s;
	while (step[e] != s) e++;
// 첫번재로 뒤집었던 정보를 저장한다.
	ans[0][0] = s, ans[0][1] = e;
// 한번 뒤집어 본다.
	reverse(step+s, step+e+1);

// 한번 뒤집었을때 정렬 되어 있다면 출력한다.
	s=1;
	while (s <= N && step[s] == s) s++;
	if (s == N+1) return !printf("%d %d\n1 1\n",
  ans[0][0], ans[0][1]);

// 한번 뒤집었을때 매칭되지 않은 부분을 다시 한번 찾는다.
	e=s;
	while (step[e] != s) e++;
// 두번째 뒤집은 곳을 찾아 저장한다.
	ans[1][0] = s, ans[1][1] = e;
// 뒤집어본다.
	reverse(step+s, step+e+1);

// 두번 뒤집어 보았을때 정답인지 확인한다.
	s=1;
	while (s <= N && step[s] == s) s++;
	if (s == N+1) return !printf("%d %d\n%d %d\n",ans[0][0],ans[0][1],ans[1][0],ans[1][1]);
// 두번 뒤집어도 정답이 아닌 경우 원래 상태로 돌려 놓는다.
	reverse(step+ans[1][0],step+ans[1][1]+1);
	reverse(step+ans[0][0],step+ans[0][1]+1);

// 뒤에서 부터 틀린 부분을 찾는다.
	e=N;
	while (e >= 1 && step[e] == e) e--;
	s=e;
	while (s >= 1 && step[s] != e) s--;
	printf("%d %d\n", s, e);
// 뒤쪽에서 어긋나는 부분을 먼저 뒤집는다.
	reverse(step+s, step+e+1);

// 뒤집은 뒤에 같다면 출력한다.
	while (e >= 1 && step[e] == e) e--;
	if (e == 0) return !printf("1 1\n");

// 같지 않는다면 한번 더 찾는다.
	s=e;
	while (s >= 1 && step[s] != e) s--;
// 답을 출력한다.
	printf("%d %d\n", s, e);

	return 0;
}



© 2020.08. by fbdp1202

Powered by theorydb