题意:
共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; }