现在的位置: 首页 > 综合 > 正文

【DP】塔

2018年01月14日 ⁄ 综合 ⁄ 共 1336字 ⁄ 字号 评论关闭
Description
给出N个木块,告诉你每个木块的高度,你要用这些木块搭出两座高度相同的塔,一个塔的高度为搭建它的木块的高度之和,并且一个塔至少要用一个木块。木块只能用一次,也可以不用。问在这两座塔高度相同的条件下,能够搭出的塔的最大高度是多少?


Input
第一行一个整数N(N<=50),表示木块的个数;
第二行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;
}

抱歉!评论已关闭.