3338. 双塔问题

单点时限: 1.0 sec

内存限制: 256 MB

Alice 和 Bob 在玩积木游戏。

他们找到了 n 块积木,这些积木都是正方体,棱长分别为 a1,a2,…,an。现在 Alice 和 Bob 要用这些积木垒两座高塔。他们想要这两座高塔的高度相等。问最大高度可能是多少?

摆放积木的顺序没有要求。两座高塔不能公用积木。

输入格式
第一行一个整数 n 。

第二行 n 个整数,用空格隔开,分别是 a1,a2,…,an (ai≥1,∑ni=1ai≤10 000)。

数据点规模约定:

对于 30% 的数据,1≤n≤15。
对于 100% 的数据,1≤n≤100。
输出格式
输出一个整数,表示最大高度。

如果不能完成任务,输出 0。

样例
input
6
2 3 3 3 6 8
output
11
提示
样例选择 2,3,3,6,8 这五块积木,搭出 8+3=11 和 6+3+2=11 这两座塔。所以答案是 11。

/*
思路:dp[i][j][k]:表示放第i块时,两个积木高度差为j时能够堆积的最大高度,k取0/1表示第一个塔/第二个塔。
因此放第i个积木有三种可能:不放,放在高的积木,放在低的积木。
特别的放在低的积木会有可能使当前堆积最大高度发生变化。
*/
#include
#include
using namespace std;
int dp[101][100000][2];
int main() {
	int n;
	cin>>n;
	int a[n+1];
	int sum=0;
	for(int i = 1; i <= n; i++) {
		cin>>a[i];
		sum+=a[i];
	}
	for(int i = 0; i < 101; i++)
		for(int j = 0; j < 100000; j++)
			for(int k =0; k < 2; k++)
				dp[i][j][k]=-1;
	dp[0][0][0]=dp[0][0][1]=0;
	for(int i=1; i<=n; i++) {
		for(int j=sum; j>=0; j--) {
			for(int k=0; k<=1; k++) {
				if(j>=a[i]&&dp[i-1][j-a[i]][k]>=0)
					dp[i][j][k] = max(dp[i-1][j-a[i]][k]+a[i], dp[i][j][k]);//向高塔放积木
				if(a[i]>j&&dp[i-1][a[i]-j][k]>=0)
					dp[i][j][k] = max(dp[i-1][a[i]-j][k]+j, dp[i][j][k]);//向低塔放积木且低塔放完积木成为高塔
				if(a[i]+j<=sum&&dp[i-1][a[i]+j][k]>=0)
					dp[i][j][k] = max(dp[i-1][a[i]+j][k], dp[i][j][k]);//低塔放完积木还是低塔
				if(dp[i-1][j][k]>=0)
					dp[i][j][k] = max(dp[i-1][j][k], dp[i][j][k]);//不放积木
			}
		}
	}
	
	cout<<max(dp[n][0][0],dp[n][0][1]);
	return 0;
}

你可能感兴趣的:(华师大OJ)