我們用較為簡潔的語言描述一下約瑟夫問題:
有n個人從0----n-1進行編號,然後進行0----m-1的報數,報數到m-1的人出列,然後從下乙個人繼續開始新一輪的報數,最後剩下乙個人為勝者。
其實我們可以重新看待一下約瑟夫問題,當沒刪除乙個人之後,我們從這個人後面的那個人重新開始0----n-2的編號,然後刪除(m-1)%(n-1)的人,我們看具體的乙個例子就比較好理解。
n=5,m=3
0 1 2 3 4
0 1 2 刪除編號為2的人,從3開始繼續0到2的報數
2 0 1刪除編號為0的人。
如果我們一直n-1個人刪除之後剩下的人是編號為多少,那麼我們可以從n個人原始的編號與重編號的關係得到n個人的情況下刪除的人的編號。
我們定義dp[i]表示i個人的時候剩下的最後乙個人的編號,那麼根據重編號的情況,我們可以得到遞推式dp[n] = (m%n+dp[n-1])%n。
這樣直接從模擬的時間複雜度降低為o(n)了,其實很多關於刪除重編號的問題都可以用這種思路來做,將原問題減小為乙個更小的相同的問題,當得到子問題的解之後,通過回溯得到原問題的解。
其實**很簡單,有需要的可以看一下下面的**(n、m的定義和上面是一致的):
#includeint dp[100];
int main()
printf("%d\n",dp[n]);
}return 0;
}
約瑟夫問題數學解法
寫完密碼約瑟夫就想到原來看到約瑟夫問題的乙個數學解法 很巧妙很簡單 不過只能推出最後乙個出列的人 無論是用鍊錶實現還是用陣列實現都有乙個共同點 要模擬整個遊戲過程,不僅程式寫起來比較煩,而且時間複雜度高達o nm 當n,m非常大 例如上百萬,上千萬 的時候,幾乎是沒有辦法在短時間內出結果的。我們注意...
約瑟夫問題數學解法
from 問題描述 n個人 編號0 n 1 從0開始報數,報到 m 1 的退出,剩下的人繼續從0開始報數。求勝利者的編號。我們知道第乙個人 編號一定是m 1 n 出列之後,剩下的n 1個人組成了乙個新的約瑟夫環 以編號為k m n的人開始 k k 1 k 2 n 2,n 1,0,1,2,k 2並且從...
約瑟夫問題數學解法
對於約瑟夫問題,今天看到了一篇好帖子,是用數學方法處理的,感覺還不錯的 無論是用鍊錶實現還是用陣列實現都有乙個共同點 要模擬整個遊戲過程,不僅程式寫起 來比較煩,而且時間複雜度高達o nm 當n,m非常大 例如上百萬,上千萬 的時候,幾乎是 沒有辦法在短時間內出結果的。我們注意到原問題僅僅是要求出最...