sicily 1176 two ends 动态规划解题

1176. Two Ends

Constraints

Time Limit: 1 secs, Memory Limit: 64 MB

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.

Sample Input

4 3 2 10 4
8 1 2 3 4 5 6 7 8
8 2 2 1 5 3 8 7 3
0

Sample Output

In game 1, the greedy strategy might lose by as many as 7 points.
In game 2, the greedy strategy might lose by as many as 4 points.
In game 3, the greedy strategy might lose by as many as 5 points.
#include <iostream>
#include <string.h>
using namespace std;

int point1_dp(int a, int b);
int nums[1010];
int dp[1010][1010];

int main() {
	int n;
	int num = 1;
	while (cin >> n && n) {
		memset(nums, 0, sizeof(nums));
		memset(dp, -1, sizeof(dp));
		int sum = 0;
		int value = 0;
		for (int i = 1; i <= n; i++) {
			cin >> value;
			nums[i] = value;
			sum += value;
		}
		int point1 = point1_dp(1, n);
		int point2 = sum - point1;
		cout << "In game " << num++ << ", the greedy strategy might lose by as many as " << point1 - point2 << " points." << endl;
	}
	return 0;
} 

//该函数为带缓存的自顶向下的动态规划方法
int point1_dp(int a, int b) {
	int start_l = 0, start_r = 0;
	if (b - a == 1) {
		if (nums[a] > nums[b]) {
			return dp[a][b] = nums[a];
		} else {
			return dp[a][b] = nums[b];
		}
	}
	//未加这个会超时 ,即每次一旦求得dp[a][b]的值,则直接返回而不用继续算下去了
	if (dp[a][b] != -1) {
		return dp[a][b];
	}
	//从左开始
	//若用 > 会wrong answer ,因为规定当相等时,优先从左选
	if (nums[a+1] >= nums[b]) {
		start_l += nums[a] + point1_dp(a+2, b);
	} else {
		start_l += nums[a] + point1_dp(a+1, b-1);
	}
	//从右开始
	if (nums[a] >= nums[b-1]) {
		start_r += nums[b] + point1_dp(a+1, b-1);
	} else {
		start_r += nums[b] + point1_dp(a, b-2);
	}

	//动态规划求最优解
	if (start_l > start_r) {
		dp[a][b] = start_l;
	} else {
		dp[a][b] = start_r;
	}
	return dp[a][b];
}

  

时间: 2024-10-13 12:03:57

sicily 1176 two ends 动态规划解题的相关文章

Sicily 1176 Two Ends

1176. Two Ends Constraints Time Limit: 1 secs, Memory Limit: 64 MB 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 c

sicily 1176. Two Ends (Top-down 动态规划+记忆化搜索 v.s. Bottom-up 动态规划)

DescriptionIn 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. T

sicily 1176 (动态规划)

题目连接:sicily 1176 解题思路: 题目看上去像是一道博弈的题,又像是一道区间型DP的题目(矩阵取数),而它跟矩阵取数的区别就是他是两个人在取数,所以每次对一个区间,我们应分两种情况考虑:第一个人取左边的数和取右边的数,而在分别考虑这两种情况时,我们又要根据贪心法则来获取上一个取数的区间.状态方程有点复杂,直接上代码了: // Problem#: 1176 // Submission#: 3601655 // The source code is licensed under Crea

Sicily 1308. Dependencies among J 解题报告

题目:1308. Dependencies among J 思路: 比较简单的一道题,要知道m最早完成的时间,只需要找出所有需要在m之前完成的工作,将它们的完成时间加起来即可.这里使用vector的数组存储每个结点的邻接点,从结点m开始,依次宽度优先搜索m的每个邻接点...数组visited记录每个结点是否被访问过,遇到已经访问过的结点直接跳过. 读取的时候一开始没有找到解决办法,要读取一行的数字,并且要判断是否换行,可以首先读取第一个数即完成时间,然后用getchar读取一个字符,如果是'\n

动态规划解题的一般思路

*  许多求最优解的问题可以用动态规划来解决. *  首先要把原问题分解为若干个子问题.注意单纯的递归往往会导致子问题被重复计算,用动态规划的方法,子问题的解一旦求出就要被保存,所以每个子问题只需求解一次. *  子问题经常和原问题形式相似,有时甚至完全一样,只不过规模从原来的n 变成了n-1,或从原来的n×m 变成了n×(m-1) ……等等. *  找到子问题,就意味着找到了将整个问题逐渐分解的办法. *  分解下去,直到最底层规模最小的的子问题可以一目了然地看出解. *  每一层子问题的解决

SOJ 1176 Two Ends

题目大意:首先输入n(n ≤ 1000),n为偶数,接着输入n个整数,n个整数的和不超过1,000,000.两个人每次只能从两端取数,第一个人A可以用任意策略,第二个人B用贪心策略(左右数相等取左数).求在保证第一个人取得的和最大的前提下,两人取数和之差的最大值. 解题思路:动态规划.突破口在于A能取两头的数,B只能取两头最大数(相同取左),而每次取完一个数,能取数的区间就会减少一个.对A来说,每次取数有两种选择,如果A知道在更少区间范围的最优和之差,则可以作出最优的选择.对B来说,每次只能用贪

1176. Two Ends

题目链接地址:http://soj.me/1176 题目大意:两头取数.第一个人随机取,第二个人用贪婪算法(每次都取大的),求两人取数在第一个人赢的情况下的最大分差.使用贪婪算法时,如果左右两边相等,取左边的. 核心算法:动态规划. 设数组arr[a][b]是在数列区间[a,b]上的最大分差. 递推公式: 1.第一个人取左边的数arr[a] if(arr[a+1] >=  arr[b])  point1 = input[a] - input[a+1] + dp(a+2,b); else poin

poj1651 最优矩阵乘法动态规划解题

题目描述: 有若干个矩阵{Ai},元素都为整数且已知矩阵大小. 如果要计算所有矩阵的乘积A1 * A2 * A3 .. Am,最少要多少次整数乘法? 输入 第一行一个整数n(n <= 100),表示一共有n-1个矩阵.第二行n个整数B1, B2, B3... Bn(Bi <= 100),第i个数Bi表示第i个矩阵的行数和第i-1个矩阵的列数.等价地,可以认为第j个矩阵Aj(1 <= j <= n - 1)的行数为Bj,列数为Bj+1. 输出 一个整数,表示最少所需的乘法次数 采用动

如何运用动态规划解题

本文内容整理自中国大学MOOC郭炜老师的程序设计与算法(二) 首先由数字三角形问题出发( ̄︶ ̄) ,题目描述如下:       7          3   8        8   1   0     2   7   4   4   4   5   2   6   5 在上面的数字三角形中寻找一条从顶部到底部的路径,使得路径上所经过的数字之和最大.路径上的每一步都只能往左下或右下走.只需要求出这个最大和即可,不必给出具体路径.(三角形的行数大于1小于100,数字为0~99) 输入: 第一行是数