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。
輸入樣例
1
2
3
4
5
0
輸出樣例
0
1
0
0
1
題解:這個跟上一個有區別。因爲上一個每次只能取定數,而且自己想取多少跟上次對方取多少沒有關聯,所以直接用一維數組就可以存。但這個題是這次的不能超過上次的兩倍,所以要記錄上次取了多少,並且每次的狀態應爲本次剩多少,且本次最多能取多少,即peanut[i][j],表示當前還剩 i ,最多能取 j 。接下來分情況討論,當 j>i-1時候,即當前剩餘 i 時我能取的數目大於 i-1,那麼我直接取 i-1 然後讓Tom取最後一個就贏;若不能取得只剩下一個,即 j<i-1,那麼假設此時取 k ,則剩餘i-k且下次最多能取2k,那麼求在所有情況下是否peanut[i-k][2*k]==1,若有一種情況不是則立馬自己先取,此段代碼應爲:
for(int i=2;i<=n;i++)
{
for(int j=i-1;j<=n;j++)
peanut[i][j]=1;//即第一種情況,這樣肯定都一次性取的還剩一個,Jerry勝出
for(int j=0;j<i-1;j++)//若這次不能一次性取的還剩一個
{
int flag=0;
for(int k=1;k<=j;k++)//這次取了k顆,
{
if(peanut[i-k][2*k]==0)//
{
flag=1;
break;
}
}
peanut[i][j]=flag;
}
}
整體代碼如下:
#include <iostream>
#include<stdio.h>
using namespace std;
int n;
int peanut[1001][1001];
int take(int n)
{
for(int i=2;i<=n;i++)
{
for(int j=i-1;j<=n;j++)
peanut[i][j]=1;//即第一種情況,這樣肯定都一次性取的還剩一個,Jerry勝出
for(int j=0;j<i-1;j++)//若這次不能一次性取的還剩一個
{
int flag=0;
for(int k=1;k<=j;k++)//這次取了k顆,
{
if(peanut[i-k][2*k]==0)//
{
flag=1;
break;
}
}
peanut[i][j]=flag;
}
}
return 0;
}
int main()
{
while(scanf("%d",&n)&&n)
{
if(n==1)
cout<<0<<endl;
else
{
take(n);
cout<<peanut[n][1]<<endl;
}
}
return 0;
}