1. 程式人生 > >【解題報告】NYOJ 518 取球遊戲 -- 簡單博弈

【解題報告】NYOJ 518 取球遊戲 -- 簡單博弈

由於題目的要求,兩個人取球,其中每人每一次必取 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};

//*-1表示0個球的情況不存在,存了8個球進去了下標從0開始的 *//

然後 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;
}