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;
}