uva 10891
来源:互联网 发布:php周末培训班 编辑:程序博客网 时间:2024/06/15 16:06
转自法力无边的厚白书。
题意:给出一个n个数的序列,两个人轮流从左端或右端开始取任意数。求第一人的数减去第二个人的最大值。
这一题,我们考虑从左边取还是从右边取,取多少个数。可以枚举每个状态。
dp[l[[r],表示从l到r,最大可以得到的数。它可以由dp[k][r], dp[l][m]得来,k = l + 1---> r m = l ---- >r - 1。k和m相当于枚举取 1 -> n - 1个数的所有情况,也就是省下的数被取的情况,也就是另一个人取的最好情况。如果另一个人的最好情况大于0,那么就取完,如果小于0,那么就按照最优解的情况取。如何取完,需要m = 0。
#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn = 100 + 5;int dp[maxn][maxn], num[maxn], sum[maxn];bool vis[maxn][maxn];int DP(int l, int r){ if(vis[l][r]) return dp[l][r]; vis[l][r] = 1; int m = 0;//能使甚至取完所有数 for(int k = l + 1; k <= r; k++) m = min(m, DP(k, r)); for(int k = l; k < r; k++) m = min(m, DP(l, k)); dp[l][r] = sum[r] - sum[l - 1] - m; //printf("%d %d %d\n", m, l, r); return dp[l][r];}int main(){ int n; sum[0] = 0; while(scanf("%d", &n) == 1 && n) { //memset(dp, 0, sizeof(dp)); memset(vis, 0, sizeof(vis)); for(int i = 1; i <= n; i++) { scanf("%d", &num[i]); sum[i] = sum[i - 1] + num[i]; } printf("%d\n", 2 * DP(1, n) - sum[n]);//ans = DP(1, n) - ( sum[n] - DP(1, n) ) } return 0;}
阅读全文
0 0
- uva 10891
- UVa 10891
- UVA 10891
- UVA 10891
- uva 10891
- UVa 10891
- uva 10891
- UVA 10891
- uva 10891 sum
- uva 10891(dp+博弈)
- UVA 10891【区间dp】
- Uva 10891 dp
- uva
- UVA
- UVA
- UVA
- uva
- UVA
- 14.(1)Struts2_值栈
- S7300通过BCNet和S7-1200/1500等西门子PLC数据交换
- USB键盘鼠标报告描述符解释
- main函数的三个参数
- CGAffineTransformMake…… 和 CGAffineTransform……的区别
- uva 10891
- chromedriver与chrome对应版本及下载地址
- java.net.SocketException: Unexpected end of file from server
- js+html空间数据编码问题--以姓名为例(代码设涉及文件读取,文本数字提取,特别是文本x,y坐标的提取)
- 移动数据分析服务使用教程
- win7如何添加开机启动程序(开机就自动运行打开)
- 用户信息表练习/删除/全选/添加
- Idea和eclipse优缺点
- spring和springmvc整合案例