UVA 437 The Tower of Babylon (DAG上的无源最长路 or LIS)

题目大意

有n种长宽高为x,y,z的砖头,每种都有无数个。

砖头可以用不同姿势的方向来盖。

砖头a以某种姿势可以盖在砖头b上,当且仅当a的底部的长宽都要比b的底部长宽要小。

问最高可以建多高?


思路:按图论的最长路dp也可,用 LIS也可以也就相当于把DAG拓扑排序了一下
//0 KB 19 ms
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int a,b,h;}block[100];
int n;
int dp[100];
void add_block(int x,int a,int b,int h)
{
    block[x].a=a;
    block[x].b=b;
    block[x].h=h;
}
bool ok(int x,int y)
{
    if(block[x].a>block[y].a&&block[x].b>block[y].b) return true;
    if(block[x].b>block[y].a&&block[x].a>block[y].b) return true;
    return false;
}
int memrize(int x)
{
    int &ans=dp[x];
    if(ans>0) return ans;
    ans=block[x].h;
    for(int i=1;i<=3*n;i++){
        if(ok(x,i)) ans=max(ans,memrize(i)+block[x].h);
    }
    return ans;
}
void print(int x){ //调试检验打印方案
    printf("(%d %d %d)\n",block[x].a,block[x].b,block[x].h);
    for(int i=1;i<=3*n;i++) if(ok(x,i)&&dp[x]==dp[i]+block[x].h) {
        print(i);
        break;
    }
}
int main()
{
    int cnt=0;
    while(scanf("%d",&n),n){
        int a,b,c;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&a,&b,&c);
            add_block(i,a,b,c);
            add_block(i+n,a,c,b);
            add_block(i+2*n,b,c,a);
        }
        int ans=-(1<<30);
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=3*n;i++)
            ans=max(ans,memrize(i));
        printf("Case %d: maximum height = %d\n",++cnt,ans);
    }
    return 0;
}


你可能感兴趣的:(UVA 437 The Tower of Babylon (DAG上的无源最长路 or LIS))