1 条题解
-
0
解题思路:
这是一个博弈论问题,关键在于确定每个石子数的必胜态或必败态。我们可以使用动态规划来解决:
定义状态:
表示剩余个石子时,当前玩家是否有必胜策略(表示必胜,表示必败)。
状态转移:
对于当前石子数,当前玩家可以取到个石子(是当前玩家的最大取石子数)。
如果存在某个( ≤ ≤ ),使得为必败态(即 = ),则当前玩家可以必胜( = )。
否则,当前玩家必败( = )。
玩家轮换:
玩家按顺序轮流取石子,因此当前玩家的编号可以通过轮次计算。
初始条件:
= :没有石子可取时,当前玩家输。
解题方法:
动态规划表初始化:
初始化数组,大小为 + ,初始值为。
填充动态规划表:
对于每个石子数从到:
计算当前玩家编号。
检查当前玩家是否可以取个石子,使得 = 。
如果存在这样的,则 = ;否则 = 。
输出结果:
初始石子数为时,的值即为答案。
C++代码实现:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int dp[25][(1<<14)+10]; int n,S,a[25]; int dfs(int x,int sum){ if(sum==0) return dp[x][sum]=1; if(dp[x][sum]!=-1) return dp[x][sum]; for(int i=1;i<=a[x]&&i<=sum;i++){ //能达到必败态的是必胜态 if(!dfs((x+1)%n,sum-i)) return dp[x][sum]=1; } //只能达到必胜态的是必败态 return dp[x][sum]=0; } int main() { while(scanf("%d",&n)&&n){ scanf("%d",&S); n<<=1; for(int i=0;i<n;i++){ scanf("%d",&a[i]); } memset(dp,-1,sizeof(dp)); printf("%d\n",dfs(0,S)); } }
- 1
信息
- ID
- 1069
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者