题意:
共n轮,s个石头和两队人,两队人轮流拿,第i轮两队分别只能拿1~M[(2*i-1)%(2*n)]和1~M[(2*i)%(2*n)]个石头,拿到最后那个石头的队输;
就拿最后一组样例来说,循环中共3轮,共97个石头,第一轮两队分别拿不超过8个和7个石头,第二轮6个和5个,第三轮4个和3个,然后又是8个和7个......
Input
n S M[1] M[2] . . . M[2*n]
1 <= n <= 10, 1 <= Mi <= 16, and 1 <= S < 2^13.
Output
赢输出1,输输出0
Sample Input
1 101 4 4 1 100 4 4 3 97 8 7 6 5 4 3 0
Sample Output
0 1 1
必胜态有至少一种方法转移到必败态
必败态只能转移到必胜态
然后就可以dp了
dp[i][j]表示第i次还剩下j个石头时,1为胜,0为败
然后dfs一下,记忆化一下已经访问过的就好了
#include<cstdio>
#include<cstring>
using namespace std;
int a[20],dp[20][9000],n;
int dfs(int k,int left)
{
if(dp[k][left]!=-1) return dp[k][left];
if(left==0) return dp[k][left]=1; //当剩下石头数量是0时,是胜的
for(int i=1;i<=a[k]&&i<=left;i++)
{
if(!dfs((k+1)%(2*n),left-i)) return dp[k][left]=1; //如果可以转移到必败态,那么就是必胜态
}
return dp[k][left]=0;
}
int main()
{
int s;
while(~scanf("%d",&n)&&n)
{
scanf("%d",&s);
for(int i=0;i<2*n;i++) scanf("%d",&a[i]);
memset(dp,-1,sizeof(dp));
printf("%d\n",dfs(0,s));
}
return 0;
}