藍橋杯 取球遊戲(博弈)
阿新 • • 發佈:2019-01-10
Problem Description
今盒子裡有n個小球,A、B兩人輪流從盒中取球,每個人都可以看到另一個人取了多少個,也可以看到盒中還剩下多少個,並且兩人都很聰明,不會做出錯誤的判斷。我們約定:
每個人從盒子中取出的球的數目必須是:1,3,7或者8個。
輪到某一方取球時不能棄權!
A先取球,然後雙方交替取球,直到取完。
被迫拿到最後一個球的一方為負方(輸方)
請程式設計確定出在雙方都不判斷失誤的情況下,對於特定的初始球數,A是否能贏?
Input
首先是一個整數n(n<100),表示接下來有n個整數。然後是n個整數,每個佔一行(整數<10000),表示初始球數。Output
輸出n行,表示A的輸贏情況(輸為0,贏為1)Sample Input
4 1 2 10 18
Sample Output
0 1 1 0
解題思路:這個題我發現了一個規律,初始球是從小到大開始計算,前四個球的時候直接初始化,之後的例如初始球為5的時候A可能取得情況為一個或者三個,當取一個的時候B取得情況也有兩種1.B取一個的時候,這個時候剩下三個,則三個和初始球為三的時候的情況是一樣的,所以可以直接得到這個時候的誰輸誰贏,2.B取三個的時候,這個時候剩下一個,這一個和初始球為1的時候的情況是一樣的。因為B不會做出錯誤的判斷,所以這個時候只有當B取球之後判斷的結果都為輸的時候A才會贏。同理A取三個的時候也是這樣來計算。也就是說對於任何情況,首先讓A取一次,然後再讓B取一次,這個時候剩下的球的數量可以根據之前計算得出結果,然後遞推;
#include<stdio.h> #include<string.h> #include<ctype.h> int vis[20000]; int ff(int x) { if(x>8) return vis[x-8]&&vis[x-7]&&vis[x-3]&&vis[x-1]; else if(x>7) return vis[x-7]&&vis[x-3]&&vis[x-1]; else if(x>3) return vis[x-1]&&vis[x-3]; else if(x>1) return vis[x-1]; else return 1; } int main() { int l,n,m,i,j; memset(vis,0,sizeof(vis)); vis[2]=1;vis[4]=1; for(i=5;i<10010;i++){ if(i>8) vis[i]=ff(i-1)||ff(i-3)||ff(i-7)||ff(i-8); else if(i>7) vis[i]=ff(i-1)||ff(i-3)||ff(i-7); else if(i>3) vis[i]=ff(i-1)||ff(i-3); else if(i>1) vis[i]=ff(i-1); } scanf("%d",&l); while(l--){ scanf("%d",&n); printf("%d\n",vis[n]); } return 0; }
當然也有一個簡單的方法,如果你足夠勤快的話,吧資料從一開始推到二十左右你就會發現這個題每十五個數的結果是一個迴圈,所以只需要將前十五個大表,之後對16取餘加一,直接輸出就好了;