好题。搜的题解敲的,没什么好多说的。但是还是想说两点:
1.本来一直不理解为什么这种博弈的问题可以用DP去做,因为双方都采用最优策略的情况下,不知道他会如何选择,但是今天明白了,这种博弈问题,对于给定的一个状态,其结果就已经是确定了的。因此可以由一个最初的确定的状态搜出所有的其他状态。另外,这里的dp数组只要赋值一次就可以了,因为不管输入的数据怎么变,给定的状态的结果是不会变的。
2.能在现场赛中做出这种难度的DP,是我的目标,当然,这还需要很多的努力和练习。毕竟就算这道题告诉我是DP了,我也不知道怎么设计状态。还有好几个容易出问题的小细节我都出问题了。差距还是很大的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 int d[55][55000]; 4 int dp(int i,int j){ 5 int &ans = d[i][j]; 6 if(ans != -1) return ans; 7 if(j == 1) return ans = dp(i+1,0); 8 ans = 0; 9 if(i >= 1 && !dp(i-1,j)) ans = 1; 10 if(i >= 1 && j && !dp(i-1,j+1)) ans = 1; 11 if(i >= 2 && ((j && !dp(i-2,j+3)) || (!j && !dp(i-2,2)))) ans = 1; 12 if(j >= 2 && !dp(i,j-1)) ans = 1; 13 return ans; 14 } 15 int main(){ 16 int t,n; 17 scanf("%d",&t); 18 memset(d,-1,sizeof(d)); 19 for(int kase = 1;kase <= t;kase++){ 20 //memset(d,-1,sizeof(d)); 21 int a = 0,b = 0,tmp; 22 scanf("%d",&n); 23 for(int i = 0;i < n;i++){ 24 scanf("%d",&tmp); 25 if(tmp == 1) a++; 26 else b += (tmp+1); 27 } 28 if(b) b--; 29 //printf("a = %d,b = %d ",a,b); 30 if(dp(a,b)){ 31 printf("Case #%d: Alice ",kase); 32 }else{ 33 printf("Case #%d: Bob ",kase); 34 } 35 } 36 return 0; 37 }