UVA 437 - The Tower of Babylon(DAG最长路)

题目大意
有n种长宽高为x,y,z的砖头,每种都有无数个。
砖头可以用不同姿势的方向来盖。
砖头a以某种姿势可以盖在砖头b上,当且仅当a的底部的长宽都要比b的底部长宽要小。
问最高可以建多高?

思路
对于一个x,y,z砖头,它可以有3种姿势放置。
(前两个为地面,后一个为高)
x, y, z
x, z, y
y, z, x
把每种姿势都记录下来,变成了有3*n种固定姿势的砖头。
然后建图,a[i][j] = true, 表示砖头j可以盖在砖头i上。
然后就是求dag上的最长路了。

#include <bits/stdc++.h>

#define INF 0x3f3f3f3f
#define eps 1e-6
typedef long long LL;
const double pi = acos(-1.0);
const long long mod = 1e9 + 7;

using namespace std;

int a[105][105];
int d[105];
int N;

struct data
{
    int x,y,z;
}edge[105];

bool cmp(const data i,const data j)
{
    if(i.x == j.x)
    {
        if(i.y == j.y)
            return i.z < j.z;
        return i.y < j.y;
    }
    return i.x < j.x;
}

int fun(int i)
{
    int& an = d[i];
    if(an > 0)
        return an;
    an = edge[i].z;
    for(int j = 0;j < 3 * N;j++)
        if(a[i][j])
            an = max(an,fun(j) + edge[i].z);
    return an;
}


int main()
{
    int cas = 1;
    while(cin >> N && N)
    {
        int b[3];
        for(int i = 0;i < N;i++)
        {
            cin >> b[0] >> b[1] >> b[2];
            sort(b,b + 3);
            //printf("%d %d %d\n",b[0],b[1],b[2]);
            edge[3 * i].x = b[0];
            edge[3 * i].y = b[1];
            edge[3 * i].z = b[2];

            edge[3 * i + 1].x = b[0];
            edge[3 * i + 1].y = b[2];
            edge[3 * i + 1].z = b[1];

            edge[3 * i + 2].x = b[1];
            edge[3 * i + 2].y = b[2];
            edge[3 * i + 2].z = b[0];
        }
        sort(edge,edge + 3 * N,cmp);
        memset(a,0,sizeof(a));
        memset(d,0,sizeof(d));
        for(int i = 0;i < 3 * N;i++)
            for(int j = 0;j < 3 * N;j++)
                if(edge[j].x < edge[i].x && edge[j].y < edge[i].y)
                    a[i][j] = 1;
        int ans = 0;
        for(int i = 0;i < 3 * N;i++)
            ans = max(fun(i),ans);
        printf("Case %d: maximum height = ",cas++);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值