HDU 4701 Game

来源:互联网 发布:三金西瓜霜漱口水 知乎 编辑:程序博客网 时间:2024/05/29 18:26

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4701

解析:没接触过几次关于最优博弈的题目,所以只能上网找blog了,了解了之后才明白。好吧,我希望多接触

~~~~~~~~~~~~~~~~~~~~~~下面转自大牛博客http://blog.csdn.net/u010690055/article/details/10295541~~~~~~~~~~~~~~

思路:Alice和Bob得金币总和为all,然后找到第一个前缀和大于all的数,这个位置是不可能到达的点。

           eg:alice有10金币,bob有10金币,则all=20金币,共有5个商品5,6,7,8,9。这样的话第四个点8是不可能到达的,因为到那里需要26金币。

           所以找到这个点之后我们要从他前面这个点开始往前递推,可以通过dp,dp[i]就表示到达i这个点时必胜需要多少个金币

           还是这个样例eg:alice有10金币,bob有10金币,则all=20金币,共有5个商品5,6,7,8,9。

           从第三个位置开始,显然dp[3]=7,因为只要能买得起这个商品,就是必胜,第四个点时无法到达的。

           对于第二个位置,要获得必胜,有两种决策:   

                                                  决策1:直接到达后继的必胜态。即dp[2]=6+dp[3]=13;

                                                  决策2:留给对手一个必败态,即对手下一次最多只能有(dp[3]-1)=6个金币,当前有all-5=15个金币,则dp[2]=15-6=9;

                                                  两者取较小值,即dp[2]=9;

          对于第一个位置,同样的,有两种决策:

                                                  决策1:直接到达后继的必胜态。即dp[1]=5+dp[2]=14;

                                                  决策2:留给对手一个必败态,即对手下一次最多只能有(dp[2]-1)=8个金币,当前有all=20个金币,则dp[1]=20-8=12;

                                                 取较小值,dp[1]=12;

         得到了dp[1]后,只需要比较dp[1]和Alice的金币大小即可,alice的金币>=dp[1]时,alice必胜,否则必败。ect:这里10<dp[1],所以alice必败。

~~~~~~~~~~~~~~~~~~~~我不是分割线我不是分割线我不是分割线我不是分割线我不是分割线~~~~~~~~~~~~~~~~~~~~

#include"stdio.h"#include"string.h"#include"stdlib.h"#include"algorithm"using namespace std;#define INF 1000010int N,A,B;int C[INF],dp[INF],sum[INF];int main(){while(scanf("%d%d%d",&N,&A,&B) != EOF){memset(dp,0,sizeof(dp));memset(C,0,sizeof(C));memset(sum,0,sizeof(sum));for(int i = 1 ; i <= N ; i++ )scanf("%d",&C[i]);int all = A+B;int flag = -1,temp = 0;for(int i = 1; i <= N ; i ++){sum[i] = sum[i-1]+C[i]; //前面所需的总和if(all < sum[i]){flag = i-1;break;}}if(flag == -1)flag = N;dp[flag] = C[flag];for(int i = flag-1; i >= 1 ; i--){dp[i] = min(dp[i+1]+C[i],all-sum[i-1]-dp[i+1]+1);}if(dp[1] > A)printf("BOB\n");elseprintf("ALICE\n");}return 0;}