单点时限: 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<iostream>
#include<algorithm>
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;
}