HDOJ1907 SG问题
生活随笔
收集整理的這篇文章主要介紹了
HDOJ1907 SG问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:同樣是給定n個堆,每個堆可任意取,但問的是誰最后拿走最后一個,是就輸。
分析:有點意思,但是慢慢分析,也能找到必勝策略,當所有堆都為1是,偶數堆顯然是先手必勝,奇數堆顯然是先手必輸,當大于1的堆有一個時,那么我們可以討論剩下的1的堆數是奇數還是偶數,當剩下的堆是奇數時,那么,先手就可以將大于1的堆拿完,剩下奇數個1的堆顯然,對手必輸,先手必勝。當剩下的堆為偶數時,顯然我使大于1的堆為1就可以了。所以只有1個大于1的堆時,先手肯定必勝。
下面我們討論大于1的堆有n個時候,這時候,必須要進行狀態轉移,那么問題來了,轉換到那個狀態才能必勝?不難想到我將n個大于1的堆變成只有1個大于1的堆就是必勝局面。所以問題來了,如何判斷是否先手能將局勢轉換只有一個大于1的堆呢,好了這就回到了經典nim堆問題,當SG為0時,說明對手拿到了最后一個,局勢是必敗,當SG不為0時,那么先手會拿到最后一個。
#include<iostream> #include<string.h> #include<sstream> #include<set> #include<algorithm> #include<vector> #include<map> #include<queue> #include<math.h> using namespace std; const int N = 100+5;int main() {int kase;cin >> kase;while (kase--) {int m,ant,ans=0,k=0;cin >> m;for (int i = 0; i < m; i++) {cin >> ant;ans = ans ^ ant;if (ant > 1)k = 1;}if (!k) {//沒有大于1的堆時if (m%2==0)cout << "John\n";else cout << "Brother\n";}else {//有大于1的堆//看SG值是否為0,SG不為0,說明它可以轉換只有一個堆大于1的狀態//相當于普通的nim堆//誰會拿到最后一個大于1的堆!if(ans!=0)cout << "John\n";else cout << "Brother\n";}}return 0; }?
總結
以上是生活随笔為你收集整理的HDOJ1907 SG问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDOJ1536 S-nim
- 下一篇: HDOJ1517