알고리즘 문제풀이

[Algospot]알고스팟 조세푸스 문제 풀이

도리컴 2023. 2. 11. 14:23
반응형

환형 링크드리스트 개념 이용 / 비교적 쉽게 해결할 수 있었음(시간복잡도 계산 시 O(N*K) 정도?)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
/*
<문제> 시간 1초, 메모리 65536kb
조세푸스와 N-1명의 사람(총 N명)이 동그랗게 서서
임의의 한 명이 죽고 시계방향으로 K 번째 살아있는 사람 자살
조세푸스와 다른 병사 하나가 살아남기 위해 조세푸스는 첫번째 병사로부터 몇자리 떨어진 곳에 있어야 할까?
 
<입력>
C    (testcase)
N K    (둘다 <=1000 / N은 3, K는 1부터 시작)
 
<출력>
마지막 살아남는 두 사람의 번호를 오름차순으로 출력
(첫번째 자살하는 병사 번호가 1, 다른사람은 이 사람에서 시계방향으로 정해짐
 
<풀이>
환형 링크드리스트 개념 이용 / 가장 끝사람 다음은 가장 첫 사람으로 연결시켜 놓고, 죽이기 진행
*/
 
struct Person {
    int num;    //병사 번호
    Person* next;    //다음병사 위치
    Person* prev;    //이전병사 위치
};
 
int Size = 0;    //사람 수
int main() {
 
    int c; cin >> c;
    while (c--) {    //testcase
        int n, k; cin >> n >> k;    //사람 수, K번씩 이동
        Size = n;    //사람 수
        Person* first = new Person();    //첫번째 병사
        first->num = 1;
        Person* prevPerson = first;    //이전 사람 위치
        for (int i = 2; i <= n; i++) {
            Person* a = new Person();
            a->num = i;     prevPerson->next = a; a->prev = prevPerson; // 번호지정 및 이전사람과 연결
            if (i == n) {    //마지막 사람인 경우 -> 다음사람을 first로 연결
                a->next = first; first->prev = a;
            }
            prevPerson = a;    //이전사람 업데이트
        }
        //병사들 원형으로 세우기 끝
 
        Person* killman = first;    //죽을사람
        Person* ans = first;    //나중에 출력할때 쓸 사람
        while (Size > 2) {    //2명 남을때까지 죽일거    
            Person* nextKillman = killman->next;//다음에 죽을 사람
            //killman 죽이기
            killman->next->prev = killman->prev;
            killman->prev->next = killman->next;
            Size--;
            for (int i = 0; i < (k - 1+ Size % Size; i++)     //k번 이동(nextKillman 선정) - Size보다 크면 나눈 나머지만큼만 이동하면 됨
                nextKillman = nextKillman->next;
            killman = nextKillman;
        
        }
 
        if (killman->num < killman->next->num) //오름차순으로 출력
            cout << killman->num << " " << killman->next->num << endl;
        else
            cout << killman->next->num << " " << killman->num << endl;
 
    }

    return 0;
}
cs

반응형