hdu1069(dp)

hdu1069 http://acm.hdu.edu.cn/showproblem.php?pid=1069
题意:
一群研究人员设计了一个检测猴子IQ的实验。他们将一个香蕉放在了房子的屋顶,同时,给小猴子一些木块。如果猴子足够聪明,他将可以用一个木块叠加另一个木块来构建一个木塔来够到香蕉。
研究人员有N种木块,无限制提供各种木块。第i个木块是一个长方体,坐标是(xi,yi,zi)。木块摆放可以调整方向,任意两条边可以当做长方体的底边,那么另一边是高。
他们想知道最高可以搭建多少来够到房顶。问题是:在构建木塔时,一个木块要完全覆盖上面一个木块,只要上面的木块的底座两边要都小于下面木块底座的两边(我写的代码中只需上面木块的最长底边小于下面木块的最长边,另一条上面的小于下面的就可以了),因为小猴子需要可以踩的地方。这意思是,例如,木块有同样长度的底边,就不能叠。
数据:N种木块,每种木块的x, y, z;

每种木块可以无数次取,但仔细想想其实每种木块最多拿2块,比如说6 8 10,有三种情况,第一种底边6 8,高10,第二种底边6 10,高8,第三种底边8 10,高6。但据题意,第一种可以和第三种一起拿,而第二种只能单独拿,因此最多拿两块,而且不能重复。
其实dp的一种题目,可以将三种都存入,然后就变成了01背包问题啦!之后就是我们熟悉的回溯过程了
还有我的point数组x要大于等于y,这样在比较是否可以搭在j上时,只需判断(point[i].x < point[j].x && point[i].y < point[j].y)就好了^^
这道题不算难,是一种经典题型,我RE了两发,等我将dp数组从二维改为一维就AC了,为什么现在也不知道==
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

using namespace std;

struct  Node
{
    int x, y;
    int high;
}point[1100];
int dp[1100];
int comp(struct Node a, struct Node b)
{
    if(a.x == b.x)
    {
        if(a.y == b.y)
        {
            a.high > b.high;
        }
        return a.y > b.y;
    }
    return a.x > b.x;
}

int main()
{
    int n, m;
    int i, j, k, mmax, Max;
    int x, y, z;
    m = 0;
    while(~scanf("%d", &n) && n)
    {
        k = 0;   m++;
        memset(point, 0, sizeof(point));
        for(i = 0; i < n; i++)
        {
            scanf("%d%d%d", &x, &y, &z);
            if(x == y && y == z)
            {
                point[k].x = point[k].y = point[k].high = x;
                k++;
            }
            else
            {
                for(j = 0; j < 3; j++)
                {
                    if(j == 0)
                    {
                        point[k].x = max(x, y);
                        point[k].y = min(x, y);
                        point[k].high = z;
                        k++;
                    }
                    if(j == 1)
                    {
                        point[k].x = max(y, z);
                        point[k].y = min(y, z);
                        point[k].high = x; 
                        k++;
                    }
                    if(j == 2)
                    {
                        point[k].x = max(z, x);
                        point[k].y = min(z, x);
                        point[k].high = y;
                        k++;
                    }
                }
            }
        }
        sort(point, point+k, comp);
        Max = point[0].high;
        for(i = 0; i < k; i++)
        {
            dp[i] = point[i].high;
            mmax = point[i].high;
            for(j = 0; j < i; j++)
            {
                z = point[i].high;
                if(point[i].x < point[j].x && point[i].y < point[j].y)
                {
                    z += dp[j];
                }
                mmax = max(z, mmax);
            }
            dp[i] = mmax;
            Max = max(Max, mmax);
        }
        cout << "Case " << m << ": maximum height = " << Max << endl;
    }
    return 0;
}

请多指教^^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值