題目來源:https://biancheng.love/contest-ng/index.html#/41/problems
F
似乎該博弈了!
nova君陷入了困境,因為他無法在PS4游戲上憑借操作戰勝對手。機智如他,只好和對手博弈了!
nova君拿出的方案和以往有些不一樣,他說:“你可以決定石子數量和石子的取法,我來決定先後手,這樣非常公平。”他的對手覺得nova君說的有道理,於是不僅決定了每局的石子數量,還給出了k個數字,表示每次可以任意取走數量等同於這k個數字中一個的石子,k中一定有一個為1。先取完者為勝。
現在很急很關鍵,快幫nova君看看他到底應該先手還是後手才能戰勝對手。
每組測試數據兩行。
第一行兩個整數n和k,第二行k個整數,意義如題目描述。
N<=100000,k<=15
對於每組數據,輸出一行,為nova應該采取的先後手 sente \ gote
4 3
1 2 3
1 1
1
gote
sente
解題思路:給定n個石頭,和k種去除石頭的方式,每種方式可以去除一定量的石頭, 現在Sente(簡稱S),gote(簡稱O),S先手,O後手,每次每個人能選擇一種去除石頭的方式,誰去除最後一堆誰就贏了。要求出必勝之人是誰。
分析:
1.用一個dp數組記錄,對於先手者能取到的記錄為1,後手者為0.
2.初始dp數組都為0,遍歷1到n,如果dp[i]為0,說明上一手是後手取得,這樣先手就能取,把dp[i]變為1,由於是從1到n,這樣每個狀態記錄時,前面的都已經記錄好了,所以是可行的.
3.這樣最後只需要判斷dp[n]是1,還是0,就可以判斷是先手勝還是後手勝了。
狀態轉移方程為:if (i - mjmj[j] >= 0 && !dp[i - mjmj[j]]) dp[i] = 1.
給出代碼:
1 #include <bits/stdc++.h> 2 #define MAX 1000010 3 int dp[MAX],mjmj[15]; 4 5 int n,m,i,j; 6 int main() 7 { 8 while(~scanf("%d",&n)) 9 { 10 memset(dp,0,sizeof(dp)); 11 scanf("%d",&m); 12 for (i=0; i<m; i++) 13 { 14 scanf("%d",&mjmj[i]); 15 } 16 for (i=1;i<=n;++i) 17 { 18 for (j=0;j<m;++j) 19 { 20 if (i-mjmj[j]>=0&&!dp[i-mjmj[j]]) 21 { 22 dp[i]=1; 23 break; 24 } 25 } 26 } 27 if (dp[n]) 28 printf("sente\n"); 29 else 30 printf("gote\n"); 31 } 32 return 0; 33 }
推薦博客:http://blog.csdn.net/kjc19920531/article/details/8120989
推薦博客:http://blog.csdn.net/wangtaoking1/article/details/7308117