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
",2*dp(1,n)-sum[n]);
49     }
50     return 0;
51 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6920639.html