UVa10891 Game of Sum

给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取。两人都采用最优策略,A先手,问A和B各自得到数字的和的差值最大为多少?

 

区间DP

F[i][j]表示区间i~j内A能得到的最大数字和。

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=110;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 int a[mxn];
17 int sum[mxn],L[mxn][mxn],R[mxn][mxn];
18 int f[mxn][mxn];
19 int n;
20 void solve(){
21     int i,j;
22     for(i=1;i<=n;i++){
23         f[i][i]=L[i][i]=R[i][i]=a[i];
24     }
25     for(int st=2;st<=n;st++){
26         for(i=1;i<=n-st+1;i++){
27             j=i+st-1;
28             f[i][j]=sum[j]-sum[i-1]-min(min(L[i+1][j],0),R[i][j-1]);
29             L[i][j]=min(f[i][j],L[i+1][j]);
30             R[i][j]=min(f[i][j],R[i][j-1]);
31         }        
32     }
33     printf("%d\n",f[1][n]-(sum[n]-f[1][n]));
34     return;
35 }
36 int main(){
37     int i,j;
38     while(scanf("%d",&n) && n){
39         for(i=1;i<=n;i++)a[i]=read();
40         memset(f,0,sizeof f);
41         memset(L,0x3f,sizeof L);
42         memset(R,0x3f,sizeof R);
43         for(i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
44         solve();
45     }
46     return 0;
47 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6575454.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值