洛谷P1651塔

题目描述

小明很喜欢摆积木,现在他正在玩的积木是由N个木块组成的,他想用这些木块搭出两座高度相同的塔,一座塔的高度是搭建它的所有木块的高度和,并且一座塔至少要用一个木块。每个木块只能用一次,也可以不用。目前已知每块木块的高度,小明想知道在最终两个塔的高度相同的情况下,他所能搭的塔的最大高度是多少,你能帮助他吗?

输入输出格式

输入格式:

第一行为一个整数N,表示木块个数。

第二行是N个整数,表示N块木块的高度。

【数据规模】

对于100%的数据,N≤50,每块木块的高度h满足1≤h≤500000,所有木块的高度总和≤500000。

输出格式:

仅一个整数,表示能搭建的塔的最大高度,若不能搭建两座相同高度的塔,则输出“-1”。

输入输出样例

输入样例#1:

3
2 3 5

输出样例#1:

5

思路:

​ 这道题我们可以设dp[i][j]代表用前i个木块拼出的塔相差j时的较低塔的高度,初始化dp[1][a[1]]=0;(使用第一个木块) dp[1][0]=0;(不使用第一个木块),其余初始化为-1,这样这道题会有4种情况:

1.当不使用第i个木块:dp[i][j] = dp[i - 1][j];
2.当使用第i个木块且将第i个木块加到较长木块上:dp[i][j] = dp[i - 1][j - a[i]];
3.当使用第i个木块且将第i个木块加到较短木块,此时较短木块还是较短木块:dp[i][j] = dp[i - 1][j + a[i]] + a[i];
4.当使用第i个木块且将第i个木块加到较短木块,此时较短木块称为较长木块:dp[i][j] = dp[i - 1][a[i] - j] + a[i] - j;

​ 要考虑周全每种情况,最后dp[n][0]即为答案,若dp[n][0] == 0 || dp[n][0] == -1时输出-1

代码:

/*************************************************************************
	> File Name: p.cpp
	> Author: Zcy
	> Mail: [email protected]
	> Created Time: 三  1/23 18:16:17 2019
 ************************************************************************/

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

int a[55];
int sum[55] = {0};
int dp[55][500005];

int main () {
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		sum[i] = sum[i - 1] + a[i];
	}
	memset(dp, -1, sizeof(dp));
	dp[1][0] = 0;
	dp[1][a[1]] = 0;
	for (int i = 2; i <= n; i++) {
		for(int j = 0; j <= sum[i]; j++) {
			dp[i][j] = dp[i - 1][j];
			if (a[i] - j >= 0) {
				if (j + a[i] <= sum[i - 1] && dp[i - 1][j + a[i]] != -1) {
					dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i]] + a[i]);
				}
				int t = a[i] - j;
				if (dp[i - 1][t] != -1) {
					dp[i][j] = max(dp[i][j], dp[i - 1][t] + t);
				}
			} else {
				if (j + a[i] <= sum[i - 1] && dp[i - 1][j + a[i]] != -1) {
					dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i]] + a[i]);
				}
				if (j - a[i] >= 0 && dp[i - 1][j - a[i]] != -1) {
					dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i]]);
				}
			}
		}
	}
	if (dp[n][0] == 0) {
		printf("-1\n");
	} else {
		printf("%d\n", dp[n][0]);
	}
	return 0;
}

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

猜你喜欢

转载自blog.csdn.net/Ivan_zcy/article/details/87894214
今日推荐