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

题目链接
题目大意
有n种长宽高为x,y,z的砖头,每种都有无数个。
砖头可以用不同姿势来盖。
砖头a以某种姿势可以盖在砖头b上,当且仅当a的底部的长宽都要比b的底部长宽要小。
问最高可以建多高?
解析:
DAG求最长路
每种砖头有无限个,每个砖头有三种姿势,所以可以看成三种底面,为了便于判断我们可以排下序
然后进行递归动态规划(这种动态规划比递推用起来更加形象且利于理解)
dp[i]表示以i开始的最长路
所以如果可堆叠的话状态转移方程为dp[i]=max(dp[i],dp[j]+app[i].c);
最后枚举更新最大值

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define pll pair<ll,ll>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
#define rson rt<<1|1,m+1,r
#define lson rt<<1,l,m
using namespace std;
const int N=100;
int dp[N];//dp[i]表示以i开始的高度
int G[N][N];//表邻接矩阵
int cnt;
struct node
{
    int a,b,c;
}app[N];
int fi(int i)
{
    if(dp[i]>app[i].c) return dp[i];
    for(int j=0;j<cnt;j++)
    {
        if(G[i][j])
            dp[i]=max(dp[i],fi(j)+app[i].c);
    }
    return dp[i];
}
int main()
{
    ios::sync_with_stdio(false);
    int n,a,b,c,kase=1;
    while(cin>>n&&n)
    {
        cnt=0;
        memset(G,0,sizeof G);
        rep(i,1,n)
        {
            int ar[3];
            cin>>ar[0]>>ar[1]>>ar[2];
            sort(ar,ar+3);
            app[cnt].a=ar[0],app[cnt].b=ar[1],app[cnt++].c=ar[2];
            app[cnt].a=ar[0],app[cnt].b=ar[2],app[cnt++].c=ar[1];
            app[cnt].a=ar[1],app[cnt].b=ar[2],app[cnt++].c=ar[0];
        }
        for(int i=0;i<cnt;i++)
        {
            dp[i]=app[i].c;
            for(int j=0;j<cnt;j++)
            {
                if(app[i].a>app[j].a&&app[i].b>app[j].b)
                {
                    G[i][j]=1;
                }
            }
        }
        int mx=0;
        for(int i=0;i<cnt;i++)
        {
            mx=max(mx,fi(i));
        }
        cout<<"Case "<<kase++<<": maximum height = "<<mx<<endl;
    }
    return 0;
}
posted @ 2018-05-03 20:34  ffgcc  阅读(97)  评论(0编辑  收藏  举报