約瑟夫問題 swust oj 0956

2021-09-23 01:59:35 字數 2348 閱讀 9169

n個人圍成乙個圈,每個人分別標註為1、2、...、n,要求從1號從1開始報數,報到k的人出圈,接著下乙個人又從1開始報數,如此迴圈,直到只剩最後乙個人時,該人即為勝利者。例如當n=10,k=4時,依次出列的人分別為4、8、2、7、3、10,9、1、6、5,則5號位置的人為勝利者。給定n個人,請你程式設計計算出最後勝利者標號數。(要求用單迴圈鍊錶完成。)

題目就是這樣了,要求輸入兩個整數,輸出勝利者(最後乙個出圈)。題目要求用鍊錶完成,除了鍊錶方法外,還有陣列和數學公式來解決,一共三種。

首先是最常見的陣列演算法,首先定義乙個一維整形陣列a[size],並初始化為0,作為模擬所有人以及是否出圈;用乙個整形數作為報數count的編號,當等於k時,初始化;用乙個整形數m表示剩下的人數。演算法原理如下:當count等於k時,將a[i](i是當前報數人的編號)賦值為1,並初始化count,剩餘人數m自減1,報數繼續。當遇到a[i]等於1時,直接跳過,讓下乙個人報當前的數。當m等於1時,表示只剩下最後乙個人,報數結束。

操作如下

關鍵**如下(c):

#include#define size 1001

int main();

printf("%d", a[0]);

scanf("%d", &n);

scanf("%d", &k);

int flag = 0; //記錄最後乙個人

int m = n;

int s = 0;

while(m >= 1)else

if(s % k == 0)

s = 0;

a[i] = 1;

m--;

}} }

printf("%d", flag);

return 0;

}

接下來就是對數學演算法的**,陣列是直接改變「報數人」的狀態,而這個演算法是改變「報數人」邏輯上的連線關係。當「報數人」出圈後,將下乙個人的編號改為0,然後依次編號,當只剩最後乙個人時,他的編號就是0,通過倒推,可以得知這個人的編號,因為是從0開始編號的,所以這個人的實際編號應加一。但是我們只是只是求最後乙個人的編號,而不是如何所有的「報數人」出圈只剩乙個人,這是沒必要的。

「報數人」出圈大致如下:

如圖所示,n表示總人數,k表示報數的最大值,i表示剩餘人的總數,a表示最後乙個人的編號。可以看到i=5的那一行,當編號為2時,則出圈。那麼,為了重新構建新的序列,3是如何變為0的呢?不難想到,因為k=3,所以序號為3的要變為0;而0呢,是如何變為2的?因為0小於k,所以0 - k = -3,序數為負數,顯然不對。因此,但h(當前報數人的編號) - k 小於0時,應該與當前人數i相加。因為要判斷差是否小於零,可以事先讓所有的小於k的編號都加上當前總人數i,在進行求餘,就可以得到下一輪的新編號(h = h > k?  h: h + i;)。那麼,這樣就可以實現報數人出圈了。但問題是如何求得最後乙個報數人的實際編號呢?

同理,根據報數人出圈的規律,可以的知最後乙個人的編號一定為0,反推就可以得到比實際編號小一的編號。就可以得到公式a = (a + k) % i。

演算法具體實現如下:

#includeint main()

printf("%d", a + 1);

return 0;

}

參考博文:

最後就是鍊錶實現,鍊錶直接將報數人刪除,十分的形象。

用鍊錶實現,就得先建立,用結構體儲存編號的連線下乙個節點。便於操作,建立乙個迴圈鍊錶,採用頭插法儲存編號。

演算法具體實現如下:

#include#includestruct list;

void createlist(struct list *&head, int n)else

} p1->next = head;//首尾相連

}//void testout(struct list *head)while(p != head);

//}void deal(struct list *head, int m, int n)

p = head;

head = head->next;

while(n != 1)else

} printf("%d", head->data);

free(head);

}int main()

約瑟夫問題的實現 swustoj

約瑟夫問題的實現 2000 ms 65535 kb 2662 8037 n個人圍成乙個圈,每個人分別標註為1 2 n,要求從1號從1開始報數,報到k的人出圈,接著下乙個人又從1開始報數,如此迴圈,直到只剩最後乙個人時,該人即為勝利者。例如當n 10,k 4時,依次出列的人分別為4 8 2 7 3 1...

SWUSTOJ 1027 舞伴問題

源 假設在週末舞會上,男士們和女士們進入舞廳時,各自排成一隊。跳舞開始時,依次從男隊和女隊的隊頭上各出一人配成舞伴。若兩隊初始人數不相同,則較長的那一隊中未配對者等待下一輪舞曲。要求編寫程式實現舞伴問題。輸入一共5行,第一行是男生人數m 第二行依次是男生的姓名 第三行是女士的人數n 第四行依次是女士...

約瑟夫問題 約瑟夫環

約瑟夫 問題 有時也稱為約瑟夫斯置換,是乙個出現在電腦科學和數學中的問題。在計算機程式設計的演算法中,類似問題又稱為約瑟夫環。又稱 丟手絹問題 據說著名猶太歷史學家 josephus有過以下的故事 在羅馬人占領喬塔帕特後,39 個猶太人與josephus及他的朋友躲到乙個洞中,39個猶太人決定寧願死...