塔
Description
给出N个木块,告诉你每个木块的高度,你要用这些木块搭出两座高度相同的塔,一个塔的高度为搭建它的木块的高度之和,并且一个塔至少要用一个木块。木块只能用一次,也可以不用。问在这两座塔高度相同的条件下,能够搭出的塔的最大高度是多少?
Input
第一行一个整数N(N<=50),表示木块的个数;
第二行N个整数,表示N个木块的高度。
每个木块的高度范围[1,500000],所有木块的高度总和<=500000。
第二行N个整数,表示N个木块的高度。
每个木块的高度范围[1,500000],所有木块的高度总和<=500000。
Output
一个数,表示能搭建的塔的最高高度,若不能搭建两座相同的塔,则输出-1.
Sample Input
Original | Transformed |
3 2 3 5
Sample Output
Original | Transformed |
5
动态规划题目
f[i,j]表示前i个分成高度差为j的两个塔时的最大高度
f[i,j]=max{f[i-1,j], f[i-1,j+a[i]], f[i-1,j-a[i]]+a[i](j-a[i]>=0),f[i-1,abs(j-a[i])]-abs(j-a[i])+a[i](j-a[i]<0)}
答案就是f[n,0]
由于数据范围比较大,要用滚动数组减少使用内存。
#include<cstdio>
#include<cstring>
using namespace std;
int a[55],dp[2][1000005]={0};
#define max(a,b) (a)>(b)?(a):(b)
#define abs(a) (a)<0?(-a):(a)
#define inf ((1<<31)-1)
int main()
{
int n;
for(; ~scanf("%d",&n);)
{
int temp=0,summ=0;
for(int i=1; i<=n; ++i)
{
scanf("%d",&a[i]);
summ+=a[i];
}
if(n<=1)
{
printf("%d\n",-1);
continue;
}
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i=1; i<=n; ++i)
{
for(int j=0; j<=summ; ++j)
{
dp[i%2][j]=dp[(i-1)%2][j];
if(j == a[i])
dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][j - a[i]] + a[i]);
if(j < a[i] && dp[(i-1)%2][a[i] - j] -a[i] + j >= 0)
dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][a[i] - j] + j);
if(j > a[i] && dp[(i-1)%2][j - a[i]] + a[i] - j >= 0)
dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][j - a[i]] + a[i]);
if(j + a[i] <= summ)
dp[i%2][j] = max(dp[i%2][j], dp[(i-1)%2][j + a[i]]);
}
}
temp=((dp[n%2][0]==0)?-1:(dp[n%2][0]));
printf("%d\n",temp);
}
return 0;
}