https://www.acmicpc.net/problem/1158
요세푸스 문제는 다음과 같다.
1번부터 N번까지 N명의 사람이 원을 이루면서 앉아있고, 양의 정수 K(≤ N)가 주어진다. 이제 순서대로 K번째 사람을 제거한다. 한 사람이 제거되면 남은 사람들로 이루어진 원을 따라 이 과정을 계속해 나간다. 이 과정은 N명의 사람이 모두 제거될 때까지 계속된다. 원에서 사람들이 제거되는 순서를 (N, K)-요세푸스 순열이라고 한다. 예를 들어 (7, 3)-요세푸스 순열은 <3, 6, 2, 7, 5, 1, 4>이다.
N과 K가 주어지면 (N, K)-요세푸스 순열을 구하는 프로그램을 작성하시오.
첫째 줄에 N과 K가 빈 칸을 사이에 두고 순서대로 주어진다. (1 ≤ K ≤ N ≤ 5,000)
예제와 같이 요세푸스 순열을 출력한다.
#include <iostream>
#include <list>
#include <vector>
using namespace std;
int n, k, len = 0;
//리스트에서 이전 노드/다음 노드를 가리키는 변수
int pre[5001];
int nxt[5001];
//요세푸스 순열을 저장하는 변수
vector <int> v;
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> k;
//n명 만큼 돌면서 pre와 nxt를 채우고 처음과 끝을 연결
for (int i = 1; i <= n; i++) {
pre[i] = (i == 1) ? n : i - 1;
nxt[i] = (i == n) ? 1 : i + 1;
len++;
}
//i가 1부터 k되는것을 반복.
int i = 1;
//연결 리스트를 순회하며 순열 생성
for (int cur = 1; len != 0; cur = nxt[cur]) {
//k번째일 때 제거
if (i == k) {
//cur값의 양쪽에 cur을 가리키는 원소들이 더이상 cur값을 가리키지 않도록 바꾼다. cur값이 없어지도록 바꾸는거다.
pre[nxt[cur]] = pre[cur];
nxt[pre[cur]] = nxt[cur];
v.push_back(cur);
i = 1;
len--;
}
else i++;
}
//요세푸스 순열 출력
cout << "<";
for (size_t i = 0; i < v.size(); i++) {
cout << v[i];
if (i != v.size() - 1) cout << ", ";
}
cout << ">";
}
오래 걸렸다. 🤔
일단 이전/다음 노드를 만드는 배열을 만들어서 원형을 만들어야한다. cur값의 양쪽에 cur을 가리키는 원소들이 더이상 cur값을 가리키지 않고 cur원소 넘어의 원소를 가르키도록 바꾼다. cur값이 없어지도록 바꾸는거다. 그리고 cur값을 출력벡터에 넣는다.