首页 > 代码库 > UVa 10891 Sum游戏

UVa 10891 Sum游戏

https://vjudge.net/problem/UVA-10891

题意:

有一个长度为n的整数序列,两个游戏者A和B轮流取数,A先取。每次玩家只能从左端或者右端取任意数量个数,但不能两端都取。所有数都被取走后游戏结束,然后统计每个人取走的所有数之和,作为各自的得分。两个人采取的策略都是让自己的得分尽量高,并且两个人都足够聪明,求A的得分减去B的得分后的结果。

 

思路:

不管是轮到谁取数,都是在一个序列中从左边或右边开始取最大值。

那么我们就令d【i】【j】表示先手在【i~j】序列中所能取到的最大值。

状态转移时,枚举从左端开始取k个数和从右端开始取k个数即可。

 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath>10 #include<map>11 using namespace std;12 typedef long long LL;13 typedef pair<int,int> pll;14 const int INF=0x3f3f3f3f;15 const int maxn=100+5;16 17 int n;18 int a[maxn];19 int sum[maxn];20 int vis[maxn][maxn];21 int d[maxn][maxn];22 23 int dp(int i,int j)24 {25     if(vis[i][j])  return d[i][j];26     vis[i][j]=1;27 28     int m=0;29     for(int k=i+1;k<=j;k++)  m=min(m,dp(k,j));30     for(int k=j-1;k>=i;k--)  m=min(m,dp(i,k));31     d[i][j]=sum[j]-sum[i-1]-m;32     return d[i][j];33 }34 35 int main()36 {37     //freopen("D:\\input.txt","r",stdin);38     while(~scanf("%d",&n) && n)39     {40         sum[0]=0;41         for(int i=1;i<=n;i++)42         {43             scanf("%d",&a[i]);44             sum[i]=sum[i-1]+a[i];45         }46 47         memset(vis,0,sizeof(vis));48         printf("%d\n",2*dp(1,n)-sum[n]);49     }50     return 0;51 }

 

UVa 10891 Sum游戏