Description

In the two-player game "Two Ends", an even number of cards is laid out in a row. On each card, face up, is written a positive integer. Players take turns removing a card from either end of the row and placing the card in their pile. The player whose cards add up to the highest number wins the game. Now one strategy is to simply pick the card at the end that is the largest -- we'll call this the greedy strategy. However, this is not always optimal, as the following example shows: (The first player would win if she would first pick the 3 instead of the 4.)
3 2 10 4
You are to determine exactly how bad the greedy strategy is for different games when the second player uses it but the first player is free to use any strategy she wishes.

Input

There will be multiple test cases. Each test case will be contained on one line. Each line will start with an even integer n followed by n positive integers. A value of n = 0 indicates end of input. You may assume that n is no more than 1000. Furthermore, you may assume that the sum of the numbers in the list does not exceed 1,000,000.

Output

For each test case you should print one line of output of the form:

  In game m, the greedy strategy might lose by as many as p points.

where m is the number of the game (starting at game 1) and p is the maximum possible difference between the first player's score and second player's score when the second player uses the greedy strategy. When employing the greedy strategy, always take the larger end. If there is a tie, remove the left end.

题意:给定一个数列,两人轮流取数,只能从两端取,第一个取的人可以用任何策略,第二个贪心,问结束时第一个人会赢多少分。

思路就是Top-Down的动态规划+记忆化搜索或者Bottom-Up的动态规划,,复杂度O(n2)。由于有比较多的判断就不写状态转移方程了,具体见代码和注释。

Notes:

Top-Down DP + Memorization 与 Bottom-Up DP 的区别

两种写法:

1. Top-Down:

//#define JDEBUG

#include<cstdio>
#include<cstring>
#include<algorithm> int cards[];
int state[][]; /**
* Top-Down DP. Get the scores won by a in [l, r]
*
* @param l start of the interval
* @param r end of the interval
* @return the scores won by a in [l, r]
*/
int dp(int l, int r) {
// reach the end
if (l > r)
return ;
// one card
if (l == r)
return cards[l];
// [Memoization] searched
if (state[l][r] != -)
return state[l][r]; int takeLeft = , takeRight = ; // check what happens if a takes left
// cards[r] > cards[l+1], so b would take right
// narrowdown to [l+1, r-1]
if (cards[r] > cards[l + ]) {
takeLeft = dp(l + , r - ) + cards[l];
} else { // cards[r] <= cards[l+1], so b would take next left
// narrow down to [l+2, r]
takeLeft = dp(l + , r) + cards[l];
} // check what happens if a takes right
// cards[r-1] > cards[l], so b would take next right
// narrow down to [l, r-2]
if (cards[r - ] > cards[l]) {
takeRight = dp(l, r - ) + cards[r];
} else { // cards[r-1] <= cards[l], so b would take left
// narrow down to [l+1, r-1]
takeRight = dp(l + , r - ) + cards[r];
} // return the best outcome
return state[l][r] = (takeLeft > takeRight) ? takeLeft : takeRight;
} int main(void) {
#ifdef JDEBUG
freopen("1176.in", "r", stdin);
freopen("1176.out", "w", stdout);
#endif int n = ;
int game = ;
while(scanf("%d", &n) && n != ) {
// initialization
int sum = ;
memset(cards, -, sizeof(cards));
memset(state, -, sizeof(state)); for(int i = ; i < n; i++) {
scanf("%d", &cards[i]);
sum += cards[i];
} int scoreOfA = dp(, n - );
int scoreOfB = sum - scoreOfA;
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",
game++, scoreOfA - scoreOfB);
}
}

2. Bottom-Up

//#define JDEBUG
#include<cstdio>
#include<cstdlib>
#include<cstring> int cards[];
int state[][]; /**
* Bottom up DP.
*
* @param n number of cards
* @return score by which b will lose
*/
int dp(int n) {
// base case: in [i, i+1], a would take the larger one,
// so b lose by abs(cards[i] - cards[i + 1])
for (int i = ; i < n - ; i++) {
state[i][i + ] = abs(cards[i] - cards[i + ]);
} // dp starts from [l, l+3] since [l, l+1] is known
// iterate: when [l, l+intvl] are left
for (int intvl = ; intvl < n; intvl++) {
for (int l = ; l < n - intvl; l++) {
int r = l + intvl;
int takeLeft = , takeRight = ; // check what happens if a takes left
// cards[r] > cards[l+1], so b would take right
if (cards[r] > cards[l + ]) {
takeLeft = state[l + ][r - ] + cards[l] - cards[r];
} else { // cards[r] <= cards[l+1], so b would take next left
takeLeft = state[l + ][r] + cards[l] - cards[l + ];
} // check what happens if a takes right
// cards[r-1] > cards[l], so b would take next right
if (cards[r - ] > cards[l]) {
takeRight = state[l][r - ] + cards[r] - cards[r - ];
} else { // cards[r-1] <= cards[l], so b would take left
takeRight = state[l + ][r - ] + cards[r] - cards[l];
} // use the one with the best outcome
state[l][r] = takeLeft > takeRight ? takeLeft : takeRight;
}
} return state[][n - ];
} int main(void) {
#ifdef JDEBUG
freopen("1176.in", "r", stdin);
freopen("1176.out", "w", stdout);
#endif
int n = ;
int game = ; while (scanf("%d", &n) && n != ) {
// store the card numbers
for (int i = ; i < n; i++) {
scanf("%d", &cards[i]);
} memset(state, , sizeof(state));
printf("In game %d, the greedy strategy might lose by as many as %d points.\n",
game++, dp(n));
} return ;
}

sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)的更多相关文章

  1. UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)

    描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  2. Codevs_1017_乘积最大_(划分型动态规划/记忆化搜索)

    描述 http://codevs.cn/problem/1017/ 给出一个n位数,在数字中间添加k个乘号,使得最终的乘积最大. 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提 ...

  3. [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)

    题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...

  4. Poj-P1088题解【动态规划/记忆化搜索】

    本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/ 题目出处: http://poj.org/problem?id=1088 题目描述: 区域由一个二维数组给 ...

  5. 滑雪---poj1088(动态规划+记忆化搜索)

    题目链接:http://poj.org/problem?id=1088 有两种方法 一是按数值大小进行排序,然后按从小到大进行dp即可: #include <iostream> #incl ...

  6. 记忆化搜索 codevs 2241 排序二叉树

    codevs 2241 排序二叉树 ★   输入文件:bstree.in   输出文件:bstree.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 一个边长为n的正三 ...

  7. 再谈记忆化搜索 HDU-1078

    最近做DP题目,发现无论是LCS,还是有些题目涉及将动态规划的路径打印出来,而且有时候还要按格式输出,这个时候,记忆化搜索显得尤其重要,确实,记忆化搜索使用优化版本的动态规划,用起来思路清晰,非常方便 ...

  8. poj1163The Triangle(动态规划,记忆化搜索)

    7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 shows a number triangle. Write a program that calc ...

  9. HDU 1176 免费馅饼(记忆化搜索)

    免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

随机推荐

  1. K8S之Secret

    目录 简介 创建secret 1.加密用户名密码 2.加密证书文件 使用secret 1.使用volume挂载方式 2.将secret用于env 简介 secret顾名思义,用于存储一些敏感的需要加密 ...

  2. Java基础-位运算符Bitwise Operators

    Java基础-位运算符Bitwise Operators 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.位运算特点 位运算符分为按位与(&),按位或(|),按位异或(^ ...

  3. saltsack自动化配置day03:服务部署mysql部署

    一.MySQL集群需求分享 1.抽象:功能模块 把基础的写成通用 服务部署也要抽象出来模块 redis内存有的多,有的少,可以config set在线更改 redis 安装.配置.启动 mysql 安 ...

  4. 前端路由的两种模式: hash 模式和 history 模式

    随着 ajax 的使用越来越广泛,前端的页面逻辑开始变得越来越复杂,特别是spa的兴起,前端路由系统随之开始流行. 从用户的角度看,前端路由主要实现了两个功能(使用ajax更新页面状态的情况下): 记 ...

  5. bzoj千题计划142:bzoj3144: [Hnoi2013]切糕

    http://www.lydsy.com/JudgeOnline/problem.php?id=3144 如果D=2 ,两个点,高度为4,建图如下 #include<queue> #inc ...

  6. BFS:八数码问题

    #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> ...

  7. 【学习笔记】初识FreeMarker简单使用

    楔子: 之前在和同事讨论,同事说“jsp技术太古老了,有几种页面技术代替,比如FreeMarker.Velocity.thymeleaf,jsp快废弃了……”云云.我这一听有点心虚……我在后端部分越刨 ...

  8. 【BZOJ】1828: [Usaco2010 Mar]balloc 农场分配(经典贪心)

    [算法]贪心+线段树 [题意]给定n个数字ci,m个区间[a,b](1<=a,b<=10^5),每个位置最多被ci个区间覆盖,求最多选择多少区间. 附加退化问题:全部ci=1,即求最多的不 ...

  9. HDU 1010 Tempter of the Bone (广搜+减枝)

    题目链接 Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. How ...

  10. js_模块化

    https://www.cnblogs.com/scq000/p/10647128.html