[BOJ] 백준 1158번 요세푸스 문제

KwangYong·2021년 10월 27일
0

BOJ

목록 보기
11/69
post-thumbnail

링크

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값을 출력벡터에 넣는다.

profile
바른 자세로 코딩합니다 👦🏻💻

0개의 댓글