博弈論 硬幣遊戲1
阿新 • • 發佈:2018-12-23
Alice和Bob在玩這樣一個遊戲。給定k個數字a[1],a[2],…,a[k]。一開始,有x枚硬幣,Alice和Bob輪流取硬幣。每次所取硬幣的枚數一定要在a[1],a[2],…,a[k]當中。Alice先取,取走最後一枚硬幣的一方獲勝。當雙方都採取最優策略時,誰會獲勝?題目假定a[1],a[2],…,a[k]中一定有1。
限制條件:
1<=x<=10000
1<=k<=100
1<=a[i]<=x
輸入:
x=9
k=2
a={1,4}
輸出:
Alice
思路:按照我們常人的想法,當前狀態有三種狀態 必勝,必敗,或者不確定;當對了兩個聰明的人來說就只有兩種情況:必勝,必敗;下面請看必勝態,必敗態的解釋;
必敗態:有x枚硬幣,有a[0]~a[k-1]中取法,當前不管你按那種取法取,都在人家的掌控之中,都得按照人家的節奏來,因為人家和你都是一樣聰明;也就是說x-a[i] (0<=i<k)為必勝態(從x-a[i]取的人掌控著戰局),x就是必敗態;
必勝態:當前取的人,按照自己聰明的想法取,他取過之後能使得對方不管按那種方法取,都贏不了,也就是說對方不管按那種方法取,剩下的硬幣數,還是必勝態,也就是說只要自己一直按照聰明的想法取,不管對方多麼聰明都無計可施;
當前為x枚硬幣
當x==0時,為必敗態;
當x>0時
若對於某個i (0<=i<k且x-a[i]>=0)x-a[i] 為必敗態,那麼x是必勝態;
若對於任意的i(0<=i<k且x-a[i]>=0)x-a[i]為必勝態,那麼x就是必敗態;
寫程式,算是用了動態規劃的思想,從小到大推出是必勝態,還是必敗態;
程式碼:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define Max 10010 bool win[Max]; int main() { int i,j,x,k; int a[110]; while(~scanf("%d%d",&x,&k)) { for(i=0;i<k;i++) scanf("%d",&a[i]); win[0] = false; for(j=1;j<=x;j++) { win[j] = false; for(i=0;i<k;i++) { if(j>=a[i]) win[j] |= !win[j-a[i]]; //表述法一:當j>=a[i]時,只要有一個a[i],使得j-a[i]為必敗態,那麼j就為必勝態; //if(j>=a[i]&&!win[j-a[i]]) // 表述法二:和上面一樣; // win[j] = true; /*if(j>=a[i]) //表述法三: { if(win[j-a[i]]) continue; else break; }*/ } /*if(i>=k) win[j] = false; // 取任意一種情況,剩下的都為必勝態,此時就為必敗態; else win[j] = true; // 只要有一種情況取後,剩下的為必敗態,那麼此時就是必勝態(一直按照自己聰明的想法取) */ } if(win[x]) printf("Alice\n"); else printf("Bob\n"); } return 0; }