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 ...
随机推荐
- java基础-IO流对象之Properties集合
java基础-IO流对象之Properties集合 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Properties集合的特点 Properties类表示了一个持久的属性集. ...
- java基础-Arrays类常用方法介绍
java基础-Arrays类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Array类的概念 此类包含用来操作数组(比如排序和搜索)的各种方法.需要注意,如果指定 ...
- [Java] 集合框架原理之一:基本结构与源码分析
一.Collection Collection 接口定义了一些基本的方法: int size(); boolean isEmpty(); boolean add(E e); boolean addAl ...
- 转:苹果Xcode帮助文档阅读指南
一直想写这么一个东西,长期以来我发现很多初学者的问题在于不掌握学习的方法,所以,Xcode那么好的SDK文档摆在那里,对他们也起不到什么太大的作用.从论坛.微博等等地方看到的初学者提出的问题,也暴露出 ...
- JS中的异步与回调
问题的引出:在js中使用异步调用时,有可能会出现在异步的回调函数中设置调用之外的变量值,但在异步调用完成后去使用变量,却发现这些变量值并没有被成功设置的情况.如: google map中的地理编码,地 ...
- Intel 和AT&T 语法
From:http://www.cnblogs.com/killerlegend/p/3906502.html Author:KillerLegend Date:2014.8.12 Intel和AT& ...
- JAVA多线程提高十四: 面试题
前面针对多线程相关知识点进行了学习,那么我们来来看看常见的面试题: 1. 空中网面试题1 package com.kongzhongwang.interview; import java.util.c ...
- Redis实战(七)Redis开发与运维
Redis用途 1.缓存 Redis提供了键值过期时间设置, 并且也提供了灵活控制最大内存和内存溢出后的淘汰策略. 可以这么说, 一个合理的缓存设计能够为一个网站的稳定保驾护航. 2.排行榜系统 Re ...
- 详细讲解安全升级MySQL的方法
MySQL升级是非常必要的. 我们在Percona Support上列出了关于MySQL升级最佳实践的各种问题.这篇文章推荐了一些不同情况下升级MySQL的方法. 为什么MySQL升级是必须的? 原因 ...
- 20155330 2016-2017-2 《Java程序设计》第七周学习总结
20155330 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 学习目标 了解Lambda语法 了解方法引用 了解Fucntional与Stream API ...