花生米(三)

时限: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

#include <stdio.h>
int n;
int List[1001][1001]={0};//List[i][j]:剩余i粒花生米后,第一次最多取j粒花生米

void search()
{
   for(int i=2;i<=n;i++)//剩余i粒花生米
   {
        for(int j=1;j<i-1;j++)//(j=0~i-2)当前最多取j粒花生米
        {
            int flag = 0;
            for(int k=1; k<=j; k++) //测试:当前取k(1~j)粒花生米后        
            {    
                //后一次剩余i-k粒花生米,最多取2*k粒花生米
                if(!List[i-k][2*k])//List[i-k][2*k]=0,即后一次若应由Tom先取才会赢,则标记,当前Jerry先取
                {  flag = 1;   break; }
            }
            List[i][j] = flag;//List[i-k][2*k]都为1,flag仁为0,即取走k粒花生米后,总是Jerry先取才会赢则当前让Tom先取
        }
        //当前可取的花生米数量(j)已经>=剩余数量(i)-1,则Jerry只需取走i-1粒便可让Tom取最后一粒
        for(j=i-1;j<=n;j++)//(j=i-1~n)Jerry先取
             List[i][j] = 1;
   }
   printf("%d\n",List[n][1]); //最初剩余n粒花生米,第一次最多取1粒花生米
}
int main()
{
    scanf("%d",&n);//第一个测例花生米数量n
    while(n!=0)
    {
        search();
        scanf("%d",&n);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/IThaitian/p/2593943.html