花生米(三)
时限: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 <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[1010][1010]; //status[i][j]表示剩余i粒花生米,最多取j粒Tom的状态
void Search(int n)
{
for(int i = 2; i <= n; i ++) //剩余i粒花生米
{
for(int j = i-1; j <= n; j++) //最多取j粒,j>= i-1,那么只需要先取i-1,即可赢
dp[i][j] = 1;
for(int j = 1; j < i-1; j++) //最多取j粒,j<i-1
{
int flag = 0;
for(int k = 1; k <= j; k++) //如果取k粒
{
//剩余i-k粒花生米,最多取2*k粒
//任一转移状态为0,Jerry都可以在该状态时
//由原来的取法变为取2*k个,那么就会赢
if(dp[i-k][2*k] == 0)
{
flag = 1;
break;
}
}
dp[i][j] = flag;
}
}
}
int main()
{
int n;
while(cin >> n && n)
{
if(n == 1) //一粒花生米,后取
{
cout << 0 << endl;
continue;
}
Search(n); //三个for,所以n不能特别大。
cout << dp[n][1] << endl; //n粒,最多取1粒
}
}