約瑟夫問題 五種變式

2022-05-27 19:48:11 字數 4039 閱讀 2956

簡單的約瑟夫問題:使用陣列,模擬乙個圈,每次數到m就標記為已讀,並將num還原為0

接著從下乙個人開始,如果到了最後乙個人,就重新回到第乙個人,繼續開始尋找,如果沒有被標記過num(數到的數字)++,直到所有人都退出圈子結束

源**

1 #include 2 #include 3 #include 4

using

namespace

std;

5int

main()625

if (ans==n)

26break;27

}28return0;

29 }

已知n個人(以編號1,2,3...n分別表示)圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列;他的下乙個人又從1開始報數,數到m的那個人又出列;依此規律重複下去,直到圓桌周圍的人全部出列。

例如:n = 9, k = 1, m = 5

【解答】

出局人的順序為5, 1, 7, 4, 3, 6, 9, 2, 8。

第一種變法,從第k個人開始數,即把迴圈的初始值設為k即可

1 #include 2 #include 3 #include 4

using

namespace

std;

5int

main()625

if (ans==n)

26break;27

}28return0;

29 }

編號為1,2,....,n的n個人按順時針方向圍坐一圈,每人持有乙個密碼(正整數).一開始任選乙個正整數作為報數上限值m,從第乙個人開始按順時針方向自1開始順序報數,報到m時停止報數.報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下乙個人開始 重新從1報數,如此下去,直至所有人全部出列為止.試設計乙個程式求出出列順序.

測試資料:

n=7;7個人 的密碼依次為:3,1,7,2,4,8,4,首先m值為6(正確的出列順序應為6,1,4,7,2,3,5)

變式2:仍從第乙個人開始數,只是每一次m都要重新更新,我們就在每次數到當前m的同時,將m更新

1 #include 2 #include 3 #include 4

using

namespace

std;

5int

main()629

if (ans==n)

30break;31

}32return0;

33 }

n個人排成一圈。從某個人開始,按順時針方向依次編號。從編號為1的人開始順時針「一二一」報數,報到2的人退出圈子。這樣不斷迴圈下去,圈子裡的人將不斷減少。由於人的個數是有限的,因此最終會剩下乙個人。試問最後剩下的人最開始的編號。

輸入格式 input format

乙個正整數n,表示人的個數。輸入資料保證數字n不超過100。

輸出格式 output format

乙個正整數。它表示經過「一二一」報數後最後剩下的人的編號。

樣例輸入 sample input :9

樣例輸出 sample output:3

變式3:

怎麼說呢,寫的很複雜,首先它是1 2 1 2 1 2 1 2 報數的,題目描述的比較模糊。

先定義乙個dir陣列為1 2兩個數字

兩層迴圈,乙個人對應乙個數,如果這個人恰好在圈中而且報數為2,那麼我們就可以把他踢出去

1

int dir[3]=;

2for (int i = 1;i <=n;)318

19if (vis[i]==1)20

28if (i==n)

29   i=1;30

else

31    i++;

32if (j==1

)33   j=0;34

else

35    j++;

因為是乙個環,所以我們可以清楚的了解到,每次如果i=n,我們就要重新從第乙個人開始

如果這個人已經被訪問過,我們就直接計算他的下乙個人,但是應該報的數不變

完整**....好長

1 #include 2 #include 3 #include 4 #include 5

using

namespace

std;

6int

main()7;

14for (int i = 1;i <=n;)

1530

31if (vis[i]==1)32

40if (i==n)

41    i=1;42

else

43    i++;

44if (j==1

)45   j=0;46

else

47   j++;

48if (num==n-1

)

4955

return0;

56}57}

58}5960

return0;

61 }

圍繞著山頂有10個洞,狐狸要吃兔子。

兔子說:「可以,但必須找到我,我就藏身於這十個洞中,你從10號洞出發,先到1號洞找,第二次隔1個 洞找,第三次隔2個洞找,以後如此類推,次數不限。」

但狐狸從早到晚進 進出出了1000次,仍沒有找到兔子。問兔子究竟藏在哪個洞裡? 

1 #include2 #include3 #include4 #include5

using

namespace

std;

6int b[10000+5];7

intmain()820

else

2128

else

2933}34

}35for(int i=1; i<=10; i++)

3642}43

return0;

44 }

例如n=6,m=5,被殺掉的人的序號為5,4,6,2,3。最後剩下1號。

假定在圈子裡前k個為好人,後k個為壞人,你的任務是確定這樣的最少m,使得所有的壞人在第乙個好人之前被殺掉。

約瑟夫環變形 先引入joseph遞推公式,設有n個人(0,…,n-1),數m,則第i輪出局的人為

f(i)=(f(i-1)+m-1)%(n-i+1);

f(0)=0;

f(i) 表示當前子串行中要退出的那個人(當前序列編號為0~(n-i));

拿個例子說:k=4,m=30;

f(0)=0;

f(1)=(f(0)+30-1)%8=5; 序列(0,1,2,3,4,5,6,7)中的5

f(2)=(f(1)+30-1)%7=6; 序列(0,1,2,3,4,6,7)中的7

f(3)=(f(2)+30-1)%6=5; 序列(0,1,2,3,4,6)中的6

f(4)=(f(3)+30-1)%5=4; 序列(0,1,2,3,4)中的4

……..

依據題意,前k個退出的人必定是後k個人,所以只要前k輪中只要有一次f(i)小於k則此m不符合題意。

<--原**

1 #include 2 #include 3 #include 4

using

namespace

std;

5 typedef long

long

ll;6

const

int inf=int_max;

7const

int maxn = 110;8

int k,ans[20],joseph[20];9

void

init()

1022}23

if(ok) break

;24 m++;25}

26 joseph[k]=m;27}

28}29int

main()

3035

return0;

36 }

UVA 1452 Jump 約瑟夫環變式

題目大意 給出n,m,約瑟夫環共n項,每數到m殺乙個人,問剩下的倒數第3個人 倒數第2個人 倒數第1個人的編號分別是多少 題解 因為我們都知道求約瑟夫環問題是f 1 0,f n f n 1 k i 所以一開始我的想法是就用同樣的方法來推倒數第2個人,f 2 0,f n f n 1 k i 但是得出的...

約瑟夫問題兩種實現方式

陣列版本 include include main int p int malloc len sizeof int printf 請輸入步長 n scanf d pace if pace 0 if pace 0 printf 請輸入進行輪數 n scanf d time printf 請輸入您想從那...

約瑟夫問題兩種實現方式

陣列版本 include include main int p int malloc len sizeof int printf 請輸入步長 n scanf d pace if pace 0 if pace 0 printf 請輸入進行輪數 n scanf d time printf 請輸入您想從那...