sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)
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 动态规划)的更多相关文章
- UVA_437_The_Tower_of_the_Babylon_(DAG上动态规划/记忆化搜索)
描述 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- Codevs_1017_乘积最大_(划分型动态规划/记忆化搜索)
描述 http://codevs.cn/problem/1017/ 给出一个n位数,在数字中间添加k个乘号,使得最终的乘积最大. 1017 乘积最大 2000年NOIP全国联赛普及组NOIP全国联赛提 ...
- [NOIP2017] 逛公园 (最短路,动态规划&记忆化搜索)
题目链接 Solution 我只会60分暴力... 正解是 DP. 状态定义: \(f[i][j]\) 代表 \(1\) 到 \(i\) 比最短路长 \(j\) 的方案数. 那么很显然最后答案也就是 ...
- Poj-P1088题解【动态规划/记忆化搜索】
本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/ 题目出处: http://poj.org/problem?id=1088 题目描述: 区域由一个二维数组给 ...
- 滑雪---poj1088(动态规划+记忆化搜索)
题目链接:http://poj.org/problem?id=1088 有两种方法 一是按数值大小进行排序,然后按从小到大进行dp即可: #include <iostream> #incl ...
- 记忆化搜索 codevs 2241 排序二叉树
codevs 2241 排序二叉树 ★ 输入文件:bstree.in 输出文件:bstree.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] 一个边长为n的正三 ...
- 再谈记忆化搜索 HDU-1078
最近做DP题目,发现无论是LCS,还是有些题目涉及将动态规划的路径打印出来,而且有时候还要按格式输出,这个时候,记忆化搜索显得尤其重要,确实,记忆化搜索使用优化版本的动态规划,用起来思路清晰,非常方便 ...
- 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 ...
- HDU 1176 免费馅饼(记忆化搜索)
免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
随机推荐
- Django admin 忘记密码
from django.contrib.auth.models import User user = User.objects.get(username="admin") user ...
- NATS_07:NATS之top工具监控以及测量调优工具
概述 你可以使用 nats-top 来实现类似于 linux 中 top 命令的实时监控 nats 服务: 可以使用 nats 提供的工具来进行针对性的调优. 安装nats-top $ go get ...
- np.argsort函数
np.argsort函数 觉得有用的话,欢迎一起讨论相互学习~Follow Me numpy.argsort(a, axis=-1, kind='quicksort', order=None) 功能: ...
- Linux服务器上使用curl命令发送报文
报文格式如下: curl -l -H "Content-type: application/json" -X POST -d 'postdata' http://172.20.10 ...
- WAV MP3 Converter-强大的音频转换软件-特别版
From:http://www.cnblogs.com/killerlegend/p/3873909.html Author:KillerLegend Date:2014.7.28 WAV MP3 C ...
- Windows下php,mysql,apache相关安装与配置,完善中…
PHP 的安装 由于php是一个zip文件(非install版),安装较为简单解压就行.把解压的 php5.2.1-Win32重命名为 php5.并复制到安装盘目录下.例如安装路径为 c:\php5 ...
- [整理]ASP.NET vNext学习资源
http://www.hanselman.com/blog/IntroducingASPNETVNext.aspx http://blogs.msdn.com/b/dotnet/archive/201 ...
- [整理]C中的静态存储区
静态存储区:即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量.栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些 ...
- soj1047.Super Snooker(转换思路+二路求和)
Description On one of my many interplanetary travels I landed on a beautiful little planet called Cr ...
- centos6安装elasticsearch6.0
环境准备 1台centos6操作系统主机,关闭selinux及iptables官方下载elasticsearch6.0软件包:https://artifacts.elastic.co/...官方下载j ...