uva10891 - Game of Sum(递推,极大极小的思想)

题目:uva10891 - Game of Sum(递推)

题目大意:给出N个数,然后有两个小伙伴在玩游戏,每次可以从这一排数字的两侧中选择一侧开始取连续的数,必须取一个,也可以取完。这两个小伙伴都会采用最优的策略来取数,问第一个小伙伴取数的和与第2个小伙伴取数的和的差值。

解题思路:这题刚开始没什么头绪,只要碰到博弈思想的题目就没什么想法。看了别人的题解才明白。

先从简单的情况来讲如果每个小伙伴只能从两侧的一侧取一个数的话, dp【i】【j】:小伙伴在第i个数字到第j个数字能取得的最大值; sum【i】【j】 :第i个数字到第j个数字的连续和。

那么递推式dp【i][j] = sum【i】【j】 - min(dp【i + 1】【j】, dp【i】【j - 1】);

这题是可以取连续的多个数字。递推式: dp【i】【j】 = sum【i】【j】 - min (dp[i + k][j], dp[i][j - k], 0);  k>= 1 && k <= j - i - 1.  0的情况代表的是全部的数都选择的情况。这里为什么不是取最大的和,而是要用总的和减去最小的最大值,我想是因为递推的需要,并且第一个小伙伴取完剩下的给另一个小伙伴选他肯定也是选择最大的,所以第一个小伙伴取完数后要使得剩下的最大值最小的,这样第一个小伙伴就可以拿到更多,同时第二个就拿到的更少。

代码:

#include <cstdio>
#include <cstring>

typedef long long ll;
const int N = 105;
const ll INF = 0x3f3f3f3f;

ll dp[N][N], sum[N];
int v[N];
int n;

void init () {

	memset (sum , 0, sizeof (sum));
	for (int i = n; i >= 1; i--) {

		if (i == n)
			sum[i] = v[i];
		else
			sum[i] = sum[i + 1] + v[i];
	//	printf ("%lld\n", sum[i]);
		dp[i][i] = v[i];
	}
}

ll Min (const ll a, const ll b) { return a < b? a: b; }

int main () {

	while (scanf ("%d", &n) && n) {

		for (int i = 1; i <= n; i++)
			scanf ("%d", &v[i]);
		init ();

		ll mm;
		for (int len = 1; len < n; len++)
			for (int i = 1; i + len <= n; i++) {

				mm = INF;
//				printf ("%lld\n", mm);
				for (int k = 1; k <= len; k++)
					mm = Min (mm, Min (dp[i + k][i + len], dp[i][i + len - k]));

				dp[i][i + len] = sum[i] - sum[i + len + 1] - Min (0, mm);
			}

//		printf ("%lld\n", dp[1][n]);
		printf ("%lld\n", 2 * dp[1][n] - sum[1]);

	}
	return 0;
}

uva10891 - Game of Sum(递推,极大极小的思想),布布扣,bubuko.com

时间: 2024-07-30 11:35:28

uva10891 - Game of Sum(递推,极大极小的思想)的相关文章

poj 2479 Maximum sum(递推)

?? 题意:给定n个数,求两段连续不重叠子段的最大和. 思路非常easy.把原串划为两段.求两段的连续最大子串和之和,这里要先预处理一下,用lmax数组表示1到i的最大连续子串和,用rmax数组表示n到i的最大连续子串和,这样将时间复杂度降为O(n). #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include&l

第一篇 递推思想

<1> 顺推的例子 上过大学的应该都知道著名的“斐波那契”数列吧,说的是繁殖兔子的问题,题目我就大概说一下. 如果1对兔子每月能生1对小兔子,而每对小兔在它出生后的第3个月就可以生1对小兔子,如果从1对初生的小兔子开始,1年后能 繁殖多少兔子? 思路:其实这个问题我们可以将兔子划分为“1月大的兔子“,”2月大的兔子“,”3月大的兔子“. ① 初始时:            一对1月大小兔子,总数为1对. ② 第一个月:         1月大的小兔子变成2月大的兔子,总数还是1对. ③ 第二个

算法之递推思想

一: 概念 通过已知条件,利用特定关系逐步递推,最终得到结果为止,核心就是不断的利用现有信息推导出新的东西. 二:分类 当然递推中有两种,"顺推"和"逆推" 顺推:从条件推出结果. 逆推:从结果推出条件. 三: 举例 <1> 顺推的例子 上过大学的应该都知道著名的"斐波那契"数列吧,说的是繁殖兔子的问题,题目我就大概说一下. 如果1对兔子每月能生1对小兔子,而每对小兔在它出生后的第3个月就可以生1对小兔子,如果从1对初生的小兔子开始,

leetcode 304. Range Sum Query 2D - Immutable(递推)

Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). The above rectangle (with the red border) is defined by (row1, col1) = (2, 1) and (row2, co

uva 766 - Sum of powers(数学+递推)

题目连接:uva 766 - Sum of powers 题目大意:将Sk(n)=∑i=1nik化简成Sk(n)=ak+1nk+1+aknk+?+a0M 解题思路: 已知幂k,并且有(n+1)k=C(kk)nk+C(k?1k)nk?1+?+C(0k)n0结论. 所以令 (n+1)k+1?nk+1=C(kk+1)nk+C(k?1k+1)nk?1+?+C(0k+1)n0 nk+1?(n?1)k+1=C(kk+1)(n?1)k+C(k?1k+1)(n?1)k?1+?+C(0k+1)(n?1)0 - 2

[bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)

Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. Input 第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000 Output 每次的方法数 Sample Input 1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900 Sample Output 4 27 So

timus 1225 flags 基础DP 简单递推

1225. Flags Time limit: 1.0 secondMemory limit: 64 MB On the Day of the Flag of Russia a shop-owner decided to decorate the show-window of his shop with textile stripes of white, blue and red colors. He wants to satisfy the following conditions: Stri

HDU4944-FSF’s game(递推)

题目链接 题意:给定一个整数n,求∑f(i, j)(1 <= j <= i <= n).其中f(i, j) = i * j / gcd(i/k, j/k)(k为i, j的公因子) 思路:依题意,我们可以得到一个递推式ans[n] = ans[n - 1] + ∑f(n, j)(1 <= j <= n), 如果我们可以预处理∑f(n,j)这一部分的话,就可以在O(n)情况下输出答案. 对于∑f(n, j)而言,我们用aj(1 <= j <= n)表示gcd(n/k,

UVA - 10304Optimal Binary Search Tree(递推)

题目:UVA - 10304Optimal Binary Search Tree(递推) 题目大意:给出一组数,e1 < e2 < ... < en,现在要求将这些数组成一棵二叉搜索树,并且使得sum (ei * cost(ei))最小.cost(ei)表示ei到到根节点之间有多少条边. 解题思路:首先二叉搜索树要满足左节点小于根节点,右节点大于根节点.因此对于e1 < e2 < ... < en这样一组数,我们只要枚举根节点的位置ek,将这个序列分成左右子树两部分(e