标签:numbers gem 自己 第一个 ssi after inpu const rom
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1778 Accepted Submission(s): 424
题意:
Alice 和 Bob 玩游戏,有n堆宝石,每一堆都有价值,如果前一个人拿了k堆那么下一个人能够拿k堆或者k+1堆,两个人都希望自己拿到的价值与另一个人的最大,求最后价值Alice-Bob,Alice可以先拿1堆或者2堆。
代码:
//看似博弈其实是dp,由于从第一个人开始并且他只能拿1或2堆,所以这是终结状态,从后向前推,设f[0/1][i][j]表示第1/2个人从第i堆开始拿并 //且上一个人拿了j堆的最优方案(Alice拿到的-Bob拿到的),每一个人又有两种拿法即j,j+1,所以处理一下前缀和转移方程就出来了。两个人都希 //望最优即第一个人希望(Alice-Bob)最大,第二个人希望(Bob-Alice)最大,我们可以把后一项看成(Alice-Bob)最小。 //因为k最大不超过200(2+4+...+k<=n),但是数组还是太大,要滚动数组。 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int MOD=223; int f[2][233][209],sum[20009]; int main() { int t,n; scanf("%d",&t); while(t--){ sum[0]=0; memset(f,0,sizeof(f)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&sum[i]); sum[i]+=sum[i-1]; } for(int i=n;i>=1;i--){ for(int j=1;j<=200;j++){ if(i+j<=n){ f[0][i%MOD][j]=max(sum[i+j-1]-sum[i-1]+f[1][(i+j)%MOD][j],sum[i+j]-sum[i-1]+f[1][(i+j+1)%MOD][j+1]); f[1][i%MOD][j]=min(sum[i-1]-sum[i+j-1]+f[0][(i+j)%MOD][j],sum[i-1]-sum[i+j]+f[0][(i+j+1)%MOD][j+1]); }else if(i+j-1<=n){ f[0][i%MOD][j]=sum[i+j-1]-sum[i-1]+f[1][(i+j)%MOD][j]; f[1][i%MOD][j]=sum[i-1]-sum[i+j-1]+f[0][(i+j)%MOD][j]; } } } printf("%d\n",f[0][1][1]); } return 0; }
标签:numbers gem 自己 第一个 ssi after inpu const rom
原文地址:http://www.cnblogs.com/--ZHIYUAN/p/7615122.html