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. linux命令总结dd命令详解

    一:dd命令 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512:c=1:k=1024:w=2 参数注释: if=文件 ...

  2. python---基础知识回顾(六)网络编程2(处理粘包)

    前戏: 之前在python---基础知识回顾(六)网络编程异步模块中提到过粘包现象,而且在使用twisted中提到过一种处理办法,按行接收lineReceived,当收到\r\n换行符时,才去缓冲区中 ...

  3. Dubbo学习笔记3:Dubbo管理控制台与监控中心的搭建

    Dubbo源码下载与编译 本文来讲下如何在Dubbo源码编译后,得到用于搭建管理控制台的war包和监控平台的jar包. 首先需要到Github上下载Dubbo的源码,解压后如下: 在dubbo-2.5 ...

  4. Java写的数据库连接池

    原文地址: http://lgscofield.iteye.com/blog/1820521 import java.sql.*; import java.util.Enumeration; impo ...

  5. Web应用开发中的几个问题

    Introduction 由于Ajax技术在Gmail中的成功应用和高性能的V8引擎的推出使得编写Web应用变得流行 起来,使用前端技术也可以编写具有复杂交互的应用.相对于native应用,Web应用 ...

  6. 大数据测试之ETL测试工具和面试常见的问题及答案

    转载自: http://www.51testing.com/html/87/n-3722487.html 概述 商业信息和数据对于任何一个企业而言都是至关重要的.现在很多公司都投入了大量的人力.资金和 ...

  7. 【AtCoder Regular Contest 080E】Young Maids [堆][线段树]

    Young Maids Time Limit: 50 Sec  Memory Limit: 512 MB Description 给定一个排列,每次选出相邻的两个放在队头,要求字典序最小. Input ...

  8. 学号20155311 2016-2017-2 《Java程序设计》第7周学习总结

    学号20155311 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 时间的度量 格林威治时间,简称GMT时间,由观察太阳而得来:世界时,UT:国际原子时,T ...

  9. 【转】C#中PrintDocument类详解

    PrintDocument组件是用于完成打印的类,其常用属性.方法和事件如下: 属性DocumentName:字符串类型,记录打印文档时显示的文档名(例如,在打印状态对话框或打印机队列中显示). 方法 ...

  10. HDU 4500 小Q系列故事——屌丝的逆袭

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4500 解题报告:简单题,数据范围不大,直接暴力每个点,然后再比较出得分最大的点的位置和分数. #inc ...