【NOJ1084】【演算法實驗四】【DP_動態規劃】花生米(三)
阿新 • • 發佈:2018-11-07
1084.花生米(三)
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
五一長假第三天,Tom和Jerry在倉庫散步的時候又發現了一堆花生米(倉庫,又見倉庫……)。這次Tom制定分花生米規則如下:
???????1、Tom和Jerry輪流從堆中取出k粒花生米吃掉;
2、第一次取花生米的人只能取一粒,以後取花生米的數量不能超過前一個人取花生米數量的兩倍;
3、為顯示規則的公平性,Jerry可以選擇先取或者後取。
Jerry當然還是希望最後一粒花生米被Tom吃掉。請計算,Jerry為了達到目的應該先取還是後取。
輸入
本題有多個測例,每個測例的輸入是一個整數n,n大於零小於等於1000,代表花生米的數量。
n等於0表示輸入結束,不需要處理。
輸出
每個測例在單獨的一行內輸出一個整數:Jerry先取輸出1;Tom先取輸出0。
#include <iostream> #include <cmath> using namespace std; int n; int isWin[1001][1001]; int dp(int x, int k); int main() { for(int i=0; i<=1000; i++) { for(int j=0; j<=1000; j++) { isWin[i][j]=-1; } } while(cin>>n&&n) { cout<<dp(n, 1)<<endl; } return 0; } int dp(int x, int k) //當前有x顆,最多能取k顆 { if(x==1) { isWin[x][k]=0; //只剩1顆時,先取必輸 return isWin[x][k]; } else if(isWin[x][k]>=0) //備忘錄中已有,直接返回 { return isWin[x][k]; } else { int mul=1; for(int i=1; i<=x&&i<=k; i++) //從拿1顆到拿k顆中遍歷 { isWin[x-i][min(x, 2*i)]=dp(x-i, min(x, 2*i)); mul*=isWin[x-i][min(x, 2*i)]; //但凡拿完i顆後,別人先取必輸; if(mul==0) //則自己拿這i顆之前是必贏的 { break; } } isWin[x][k]=1-mul; return isWin[x][k]; } }