728x90
반응형
2505번: 두 번 뒤집기
문제
https://www.acmicpc.net/problem/2505
2505번: 두 번 뒤집기
첫줄에는 숫자판의 크기를 나타내는 정수 N (5 ≤ N ≤ 10,000)이 주어진다. 그 다음 줄에는 두 개의 구간이 뒤집혀진 놀이판의 상태를 나타내는 숫자들이 하나의 공백을 두고 나타난다.
www.acmicpc.net
풀이
먼저 왼쪽에서 오른쪽으로 진행하며 i번째 칸의 수가 i가 아닌 경우 i의 위치를 찾아 두 위치를 정답 배열에 추가하고 두 위치 사이의 모든 값을 reverse 한다. 그러면 i번째 칸의 수는 i가 되었으므로 다음 수로 넘어가 위 과정을 반복한다.
만약 정답 배열의 크기가 2보다 큰 경우, 답이 될 수 없으므로 위에서 했던 과정을 오른쪽에서 왼쪽으로 진행한다. 이유는 "단 두 번만 뒤집기 때문"이다. 정확히는 두 번째 뒤집은 위치는 처음 뒤집은 위치를 기준으로 왼쪽이 겹치거나 오른쪽이 겹치거나 둘 중 하나이기 때문이다.
정답 배열의 크기가 반드시 2 이하일 수밖에 없게 되고, 크기가 2인 경우에는 배열의 값을 모두 출력하면 된다. 크기가 1인 경우는 위치 i와 j는 i ≤ j 를 만족하기 때문에 같을 수 있으므로 1 1을 출력한다. (꼭 1이 아니어도 같은 숫자면 된다.) 마찬가지로 크기가 0인 경우에는 처음부터 정렬되어 있는 배열이었으므로 1 1을 두 번 출력하면 된다.
코드
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
vector<int> input(n), v;
vector<pair<int, int>> ans;
for (int i = 0; i < n; i++)
cin >> input[i];
v = input;
for (int i = 0; i < n; i++) {
if (v[i] == i + 1)
continue;
for (int j = i + 1; j < n; j++)
if (v[j] == i + 1) {
ans.push_back({i + 1, j + 1});
reverse(v.begin() + i, v.begin() + j + 1);
break;
}
}
if (ans.size() > 2) {
ans.clear();
v = input;
for (int j = n - 1; j >= 0; j--) {
if (v[j] == j + 1)
continue;
for (int i = j - 1; i >= 0; i--)
if (v[i] == j + 1) {
ans.push_back({i + 1, j + 1});
reverse(v.begin() + i, v.begin() + j + 1);
break;
}
}
}
if (ans.size() == 2)
for (auto [a, b] : ans)
cout << a << ' ' << b << '\n';
else if (ans.size() == 1)
cout << ans[0].first << ' ' << ans[0].second << "\n1 1";
else
cout << "1 1\n1 1";
return 0;
}
728x90
반응형
'Problem Solving > BOJ' 카테고리의 다른 글
[백준 / BOJ] C++ 2041 숫자채우기 (3) | 2023.04.15 |
---|---|
[백준 / BOJ] C++ 18116 로봇 조립 (6) | 2023.04.14 |
[백준 / BOJ] C++ 16567 바이너리 왕국 (4) | 2023.04.12 |
[백준 / BOJ] C++ 27866 문자와 문자열 (2) | 2023.04.11 |
[백준 / BOJ] C++ 6497 전력난 (6) | 2023.04.11 |