UVA 10891 Game of Sum
来源:互联网 发布:靠淘宝运费险赚钱 编辑:程序博客网 时间:2024/05/17 23:53
题目链接:http://acm.hust.edu.cn/vjudge/problem/19461
题意:一个长度为n的序列,两个人轮流取数。每次玩家可以从左端或者右端取任意数量个数,但不能两端都取。两人都希望自己的得分尽量大。当所有数都取完后,求先手取数之和减去后手取数之和。
思路:dp[l][r]表示取区间[l,r]内的数时,先手之和减去后手之和的最大值。dp[l][r] = max( sum[l,k] - dp[k+1][r] , sum[k,r] - dp[l][k-1] )分别枚举先手从左/右端取走的个数,取最大值,记忆化搜索计算答案。
还有一种方法是参考书上的递推做法,dp[l][r]表示先手取区间[l,r]内的数获得的最大值。dp[l][r] = sum[i,j] - min( dp[l+1][r] , dp[l+2][r] , dp[l+3][r]...dp[r][r] (取左端) , dp[l][l] , dp[l][l+1] , dp[l][l+2] , dp[l][l+3]....dp[l][r-1] (取右端) , 0(全部取完) );
f[l][r] = min( dp[l+1][r] , dp[l+2][r] , dp[l+3][r]...dp[r][r] )
g[l][r] = min( dp[l][l] , dp[l][l+1] , dp[l][l+2] , dp[l][l+3]....dp[l][r-1] )
dp[l][r] = sum - min( 0 , min(f[l][r] , g[l][r]) )
f和g存在递推式
#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <sstream>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod 100000007const int maxn = 109;int n;LL sum[maxn];int a[maxn];LL dp[maxn][maxn];bool flag[maxn][maxn];void init(){ sum[0] = 0; rep(i,1,n) { scanf("%d",&a[i]); sum[i] = sum[i-1] + a[i]; } Clean(flag,false);}LL dfs( int l , int r ){ if ( flag[l][r] ) return dp[l][r]; if ( l == r ) return a[l]; if ( l > r ) return 0; LL ans = sum[r] - sum[l-1]; rep(i,l,r-1) { ans = max( ans , sum[i]-sum[l-1] - dfs(i+1,r) ); ans = max( ans , sum[r] - sum[i] - dfs(l,i) ); } flag[l][r] = true; return dp[l][r] = ans;}int main(){ while( cin>>n ) { if ( !n ) break; init(); cout<<dfs(1,n)<<endl; } return 0;}
#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <sstream>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod 100000007#define mp make_pair#define fi first#define se second#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mid int m=(l+r)>>1const int maxn = 109;LL a[maxn];LL sum[maxn];LL dp[maxn][maxn]; //先手取最大值LL f[maxn][maxn];LL g[maxn][maxn];int n;void init(){ sum[0] = 0; rep(i,1,n) { cin>>a[i]; sum[i] = sum[i-1] + a[i]; dp[i][i] = a[i]; f[i][i] = g[i][i] = inf; } rep(L,2,n) { rep(i,1,n-L+1) { int j = i + L - 1; f[i][j] = min( f[i+1][j] , dp[i+1][j] ); g[i][j] = min( g[i][j-1] , dp[i][j-1] ); dp[i][j] = sum[j] - sum[i-1] - min( 0LL , min( f[i][j] , g[i][j] ) ); } } cout<<2*dp[1][n] - sum[n]<<endl;}int main(){ while(cin>>n) { if ( !n ) break; init(); } return 0;}
0 0
- uva 10891 Game of Sum
- UVA 10891 Game of Sum
- UVa 10891 Game of Sum
- Uva-10891-Game of Sum
- Uva 10891 Game of Sum
- Uva - 10891 - Game of Sum
- uva 10891 - Game of Sum
- uva 10891 game of sum
- UVA 10891 Game of Sum
- UVa 10891 - Game of Sum
- UVA 10891 Game of Sum
- uva 10891 - Game of Sum
- UVA - 10891 Game of Sum
- uva 10891 - Game of Sum
- uva 10891 - Game of Sum
- UVA 10891 Game of Sum
- UVA -10891 - Game of Sum
- uva 10891 - Game of Sum
- lk启动流程详细分析
- 八月--让英语融入生活
- 经典面试题之最长滑道(2017爱奇艺内推笔试题)
- DB2快速入门—DB2 11的安装与使用
- 7. Reverse Integer
- UVA 10891 Game of Sum
- java难点之表达式
- 理解MVC,MVP和MVVM设计模式
- 根据前序和中序推出后序
- Android成长之路-事件消费
- Android开发艺术探索 第六章 第七章
- mysql5.7免安装配置
- O_NONBLOCK,fcntl 非阻塞io读取键盘鼠标
- java调用c# dll