RomanRoulette

Roman Roulette















Time Limit:   1000MS             Memory Limit:   65535KB
Submissions:   36             Accepted:   19

Description西元67年,在羅馬和猶太人的衝突中,史學家
Josephus 和其他40個人被關在一個洞穴中。羅馬人知道 Josephus
的下落後希望他能投效羅馬帝國。但是他的同伴們卻不允許他投降。所以Josephus
建議他們彼此殺害,一個接一個,被殺的順序就由命運決定。傳統上他們決定命運的方式為:大家圍成一個圓圈,從某個人開始算起,每算到 3
個人那個人就被殺掉,如此不斷下去,直到只剩一個人。後來 Josephus 成為唯一的存活者並投降羅馬。我們有興趣的是:Josephus
如何剛好是那個存活者?真的是運氣好,還是他事先在暗地裡用 41 顆石頭練習過,或者他有一個數學的方法可以知道要站在哪一個位置才能成為最後的存活者?
聽過這個故事後,你相當的憂心要是將來某一天你也面臨同樣的情況要怎麼辦。所以你決定用你的手上型電腦寫一個程式算出應該從那個人開始算起,你才可以成為那個最後唯一存活的人。
在這個問題中,你的程式必須能解決 Josephus 描述的另一種變形。有 n 個人排成一個圓圈,面向內,依順時鐘方向編號從 1 到 n。你的位置在
1 。殺人程序由編號 i 的人開始算起(順時鐘方向),直到算到第 k 個人,那個人立刻被殺掉。然後從這個被殺的人左邊的那個人再順時鐘方向算 k
個人,那個人必須負責埋葬剛才被殺的那個人,然後回去站在剛才被殺的那個人的位置。接下來從這個人的左邊那個人算起,第 k
個人又被殺掉,如此一直下去直到只剩下一個人為止。 例如:當 n=5, k=2, i=1, 那麼被殺的順序為 2, 5, 3,
1,存活者為4。
Input輸入含有多組測試資料。
每組測試資料有2個整數 n, k 。你可以假設最多只有 100 個人。 若 n = k = 0 時代表輸入結束。請參考Sample
Input。
Output對每組測試資料輸出一開始時應該從哪一個人算起(也就是
i),才能確保你是最後唯一的存活者。請記住:你的位置在 1。以上述的例子來看,必須由第 3 個人算起,最後存活的人才能是 1

Sample Input

1 1
1 5
5 2
5 4
7 3
100 53
100 2
11 93
0 0

Sample Output

1
1
3
5
1
13
83
2

+ ?





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

/*

 * UVA_130_1.cpp

 *

 *  Created on: 2013年10月31日

 *      Author: Administrator

 */

   

#include <iostream>

#include <cstdio>

#include <vector>

   

using
namespace std;

   

/**

 * 模拟的实现使用动态数组是非常方便的,过程也很简单。数组初始存储每一个人的编号,

 * 从第0个元素(1号)开始计数,每次杀死一个人前先不要将这个人的编号删除,而是先找出要来埋他的人,

 * 将他们的编号互换,然后将埋他的人原来所在的位置删掉即可。最后计算出的是从1号开始计数,最后能幸存的人编号p,

 * 那么从你前面第p个人开始你就是安全的(你站在第1位),即n - p。这个换算的原理是显而易见的。

 */

int
main(){

    int
n,k;

    while(scanf("%d%d",&n,&k)!=EOF,n||k){

        int
i;

        vector<int> circle;

        for(i = 1 ; i <= n ; ++i){

            circle.push_back(i);

        }

   

        int
t;

        int
m = (k - 1)%circle.size();//计算第一个被杀死的人的位置

        while(circle.size() != 1){

            t = (m - 1 + k)%(circle.size() - 1);//计算替换者的位置

            t = (t + (t >= m))%circle.size();//判断替换着的位置与被杀者位置之间的关系,若被杀者的位置在替换着的前面,则需要+1

   

            circle[m] = circle[t];//将替换者一道被杀者的位置上

   

            circle.erase(circle.begin() + t);//删除替换者原来的位置

   

            m = (m  - ( t < m ) + k)%circle.size();//计算下一个被杀者的位置,因为最后删掉的其实还是替换者的位置,所以如果替换者的位置在额被杀者的前面的话,那么就要-1

        }

   

        printf("%d\n",(n - circle.front() + 1)%n + 1 );

    }

   

    return
0;

}

  

RomanRoulette,布布扣,bubuko.com

时间: 2024-10-10 05:45:14

RomanRoulette的相关文章