【算法题】砌砖块

来源:互联网 发布:天才琪露诺软件 编辑:程序博客网 时间:2024/05/19 01:10

小易有n块砖块,每一块砖块有一个高度。小易希望利用这些砖块堆砌两座相同高度的塔。为了让问题简单,砖块堆砌就是简单的高度相加,某一块砖只能使用在一座塔中一次。小易现在让能够堆砌出来的两座塔的高度尽量高,小易能否完成呢。
输入描述:
输入包括两行:
第一行为整数n(1 ≤ n ≤ 50),即一共有n块砖块
第二行为n个整数,表示每一块砖块的高度height[i] (1 ≤ height[i] ≤ 500000)

输出描述:
如果小易能堆砌出两座高度相同的塔,输出最高能拼凑的高度,如果不能则输出-1.
保证答案不大于500000。

输入例子:
3
2 3 5

输出例子:
5

知道需要动态规划,但是不知道怎么弄,牛客网上有大牛给出答案:
设两座塔为A、B;

考虑前 i 块砖头砌出的两座塔的高度差的所有可能情况:dp[i][j] 其中j表示高度差B-A

dp[i][j]存的值则为B的最大高度值

则状态转移方程为:

dp[i][j]=maxdp[i1][j]dp[i1][jhi]dp[i1][j+hi]+hii使iAiB

最终所求即为:dp[i][0]

dp矩阵过大,可使用滚动数组防止内存溢出

#include <iostream>#include <vector>#include <numeric>#include <algorithm>using namespace std;int func(vector<int>& vec){    long long sum = accumulate(vec.begin(),vec.end(),(long long) 0 );    vector<int> dp_i_1(2*sum+2,-1);//偏移sum:  sum ->  0    vector<int> dp_i_0(2*sum+2,-1);    vector<int> * p_dp1 = &dp_i_1;//dp[i]的指针    vector<int> * p_dp0 = &dp_i_0;//dp[i-1]的指针    int tmp_1(-1), tmp_2(-1), tmp_3(-1);    (*p_dp0)[sum] = 0;//dp[0][0] = 0    for (auto i = 0; i < vec.size();++i)    {        for (auto j = 0; j < 2 * sum;++j)        {            tmp_1 = -1; tmp_2 = -1; tmp_3=-1;            tmp_1 = (*p_dp0)[j];                    //第i块砖没有用上时            if (j-vec[i]>=0)            {                tmp_2 = (*p_dp0)[j - vec[i]];       //第i块砖放A塔时            }            if (j + vec[i]<2 * sum + 2 && ((*p_dp0)[j + vec[i]]!=-1))            {                tmp_3 = (*p_dp0)[j + vec[i]]+vec[i];//第i块砖放B塔时            }            (*p_dp1)[j] = max(tmp_1,max(tmp_2,tmp_3));//状态转移        }        std::swap(p_dp0, p_dp1);//滚动数组    }    if ((*p_dp0)[sum] == 0)    {        cout << -1 << endl;    }    else    {        cout << (*p_dp0)[sum] << endl;    }    return 0;}int main(){    int n = 0;    cin >> n;    vector<int> vec(n);    int sum = 0;    for (int i = 0; i < n; ++i)    {        cin >> vec[i];    }    func(vec);    return 0;}