요즘 문제가 잘 풀리지 않는다ㅜ

이 문제 사실 조금만 고민해보면 쉽게 풀리는 문제였는데, 너무 어렵게 접근했던 것 같다.

처음 떠올린 풀이를 고집하면 이제 이런 문제로 두 시간을 소비하게 되는 것이다ㅜ

시간 제한 메모리 제한 정답률
2초 256MB 49.159%

 

문제

요세푸스 문제는 다음과 같다.

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 <algorithm>
#include <queue>

using namespace std;

int n, k, tmp;

queue<int> q;



int main(int argc, char* argv[]) {
	ios_base :: sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    cin >> n >> k;
    
    for(int i=1;i<=n;i++){
        q.push(i);
    }
    
    cout << '<';
    
    while(q.size() > 1){
        for(int i=0;i<k-1;i++){
            tmp = q.front();
            q.push(tmp);
            q.pop();
        }
        
        tmp = q.front();
        cout << tmp << ", ";
        q.pop();
    }
    
    tmp = q.front();
    
    cout << tmp << ">\n";
    
    
	
	return 0;
}

해설

한 명을 넘길 때마다 q.pop(), q.push()를 하면 된다. (동그라미 모양이라고 생각하자!)

차례가 되어 죽일 때는 그냥 q.pop()을 해버리면 된다.

큐가 빌 때까지 반복하면서 출력하면 요세푸스 순열이 완성된다.

다만 한가지 주의할 점은, 그냥 출력하는 것이 아니라는 것이다.

처음과 끝에 < >를 붙여야 하므로, 큐를 다 비우지 말고, 하나를 남겨 둔 상태에서 반복문을 종료한 후(그래야 ,가 들어가지 않음) 마지막을 출력해주면 된다.

 

 

이 문제를 풀면서 느낀 점은, 알고리즘 문제 접근법은 고등학교 시절 수학 문제 접근법과 아주 유사하다는 것이다.

고등학교 때 그렇게 열심히 하면서 나름 좋은 학교도 왔고, 수능 수학까지는 자신있었다.

문제 접근법도 많이 연습했었는데, 막상 알고리즘을 풀 때 보니까 그것을 사용하지 않고 있었다.

문제를 잘 읽고(조건 등), 어떤 알고리즘을 사용해서 문제를 풀지, 제한시간내 해결할 수 있을지, 알고리즘 적으로 타당한지에 대해 좀 더 생각하고 코드를 작성해야한다고 느꼈다.

'으음 대충 이거 쓰면 되겠네' 라는 생각을 할 수록 solve하는 시간만 길어진다는 것을 깨닫게 되었다.

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기