题目:
A 和 B 在玩一个游戏,给定K个数字a1,a2,a3...ak ; 一开始有x个硬币 ; A 和 B 轮流取硬币。每次所取硬币的枚数一定在a1,a2,a3..ak ; 里面,A 先取 , 取走最后一枚的获胜 , 两个人都采取最优的策略,谁会WIN ?
分析:
博弈论的关键就在于找出必胜态 和 必败态 ;
1.既然取关了硬币就是获胜 , 那就是说到自己的时候没有硬币了,就是输了 ; 则j=0 ; 时是必败态 ;
2.如果对于某个i(1<=i<=k) , j-ai是传说中的必败态 , 那 j 就是必胜态 ; (当只有j枚硬币的时候 , 只要拿走a1枚对手就输了,那就是等于我赢了)
3.如果对于任意的i(1<=i<=k) , j-ai 都是必胜态,j就是必败态 ; (无论怎么取都是对手赢,那就是输)
难以理解的话,可以把 j 看成是当前的状态 , j-ai 是上一个状态 ; 这样可以找到j
依靠这些规则,采用动态规划的思想按照j从小到大的顺序计算必胜与必败 ; 到时我们只要看x是必胜还是必败即可 ;
#include<stdio.h> int x,k,a[20001]; bool win[20001]; int main( ) { scanf("%d %d",&x,&k); for(int i=0 ; i<k ; i++) scanf("%d",&a[i]); win[0] = false;//到自己的时候没有了就输了; for(int j=1 ; j<=x ; j++) { win[j] = false; for(int i=0 ; i<k ; i++) { win[j] |=a[i]<=j && !win[j-a[i]]; } } if(win[x]) puts("A"); else puts("B"); return 0; }
自己敲的
#include<stdio.h> int x,k,a[20001]; bool win[20001]; int main( ) { scanf("%d %d",&x,&k); for(int i=0 ; i<k ; i++) scanf("%d",&a[i]); win[0] = false;//到自己的时候没有了就输了; for(int j=1 ; j<=x ; j++) { win[j] = false; for(int i=0 ; i<k ; i++) { if(a[i]<=j) { if(win[j-a[i]]==false) win[j]=true; } } } if(win[x]) puts("A"); else puts("B"); return 0; }
题目:
意思就是两个人轮流拿硬币,Alice先拿,Alice拿的时候可以选择拿走一个或者拿走相邻的两个,谁拿完最后的石子胜利。
#include<stdio.h> int main( ) { int n ; scanf("%d",&n); if(n<=2) puts("Alice"); else puts("Bob"); return 0; }