【解題報告】NYOJ 518 取球遊戲 -- 簡單博弈
阿新 • • 發佈:2019-01-30
由於題目的要求,兩個人取球,其中每人每一次必取 1, 3, 7, 8 其中的一個數量的球,並且最後一個球被取到的人輸,因此我得出以下表格:
先我拿 | 先他拿 | 記錄表表示了初始的總球數,所對應的遊戲情況 | |||||||||
我敗 | 我勝 | 1 | 3 | 5 | 7 | 16 | 18 | 20 | 22 | 31 | ..... |
我勝 | 我敗 | 2 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | ..... |
表格中的 失敗 勝利,均是相對於“我”而言的。
因此對於A君先取球,判斷A君的遊戲情況,可以把“我先拿勝利”的情況均存在r[]陣列中並賦值為1,否則r[]陣列中其他值賦值為0,即可。
表格的具體構造過程如下:
初始值:int r[10003]={-1,0,1,0,1,0,1,0,1};
然後 i = 9;判斷 ( r[i-8] && r[i-3] && r[i-7] && r[i-1] ) ……①是否成立
成立則r[i] = 1 否則r[i] = 0;
i++,重複①
第一排的球數目為 必敗點(LP)
第二排的球數目為 必勝點(WP)
原理就是 初始球數目為LP誰先拿誰輸,如果“我”可以取完球之後將球總數變為LP,那麼對手一定輸,反之對手取完球之後將球總數變為LP,那麼“我”一定輸。
因此可以先簡單的推測出1-8個球的情況,然後從9開始利用1-8個球的情況推算後面的各個情況。只要我拿走1, 3, 7, 8其中的任意一個數量的球之後,剩餘的球數量變成了 WP ,那麼就勝利了(r[i]=1),反之就失敗了(r[i]=0)。
附原始碼:
#include <stdin.h>
int main()
{
int i,n,r[10003]={-1,0,1,0,1,0,1,0,1};
for (i=9;i<=10000;i++)
r[i]=(r[i-8] && r[i-3] && r[i-7] && r[i-1])?(0):(1);
scanf("%d",&n);
while(~scanf("%d",&n))
printf("%d\n",r[n]);
return 0;
}