【算法實驗四】--【動態規劃】--花生米(三)

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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章