P1651
塔
题目描述
小明很喜欢摆积木,现在他正在玩的积木是由 \(N\) 个木块组成的,他想用这些木块搭出两座高度相同的塔,一座塔的高度是搭建它的所有木块的高度和,并且一座塔至少要用一个木块。每个木块只能用一次,也可以不用。目前已知每块木块的高度,小明想知道在最终两个塔的高度相同的情况下,他所能搭的塔的最大高度是多少,你能帮助他吗?
输入格式
第一行为一个整数 \(N\),表示木块个数。
第二行是 \(N\) 个整数,表示 \(N\) 块木块的高度。
输出格式
仅一个整数,表示能搭建的塔的最大高度,若不能搭建两座相同高度的塔,则输出 -1。
样例 #1
样例输入 #1
3
2 3 5
样例输出 #1
5
提示
对于 \(100\%\) 的数据,\(N \le 50\) ,每块木块的高度 \(h\) 满足 \(1 \le h \le 500000\),所有木块的高度总和 \(\le 500000\)。
绝好的一道DP题!
开始用的bool pack
假做法还得了80pts 因为这种没办法保证 h和h/2用的不重复
神奇正解
f[i][j]:前i个 差值为j(>0)时较高塔的高度
则有以下状态转移:
1.ith不放
2.ith放较高的
3.ith放较低的但是仍较低
4.ith放较低的但变成了较高的
(这种不看题解谁TM会啊~)
还有个细节:最开始f要赋-INF(我也不知道为什么)
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,a[55],f[55][500005],h;//放了前i个 差值为j 的最大高度
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i],h+=a[i];
memset(f,-0x3f,sizeof(f));
// cout<<f[0][0]<<' ';
f[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=h;j++)
{
f[i][j]=max(f[i-1][j],f[i-1][j+a[i]]);
if(j-a[i]>=0)f[i][j]=max(f[i][j],f[i-1][j-a[i]]+a[i]);
else f[i][j]=max(f[i][j],f[i-1][a[i]-j]+j);
}
}
if(f[n][0]>0)cout<<f[n][0]<<"\n";
else cout<<-1<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号