The Tower of Babylon UVa 437

来源:互联网 发布:数据分析的实施过程 编辑:程序博客网 时间:2024/06/05 11:52

题目大意

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

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

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

问最高可以建多高?

思路

一个类型的木头能否搭在另一个类型的木头上是典型的二元关系,若i能搭在j上,就在j到i连一条有向边,形成一张图,问题就变成了求解图上的最长路,
#include<iostream>#include<cstring>#include<cstdio>using namespace std;struct E{int x,y,z;}a[105];struct Edge{int v,next;}e[10005];int tot,head[105],f[105],vis[105];inline void add(int u,int v){e[tot].v=v;e[tot].next=head[u];head[u]=tot++;}inline bool check(int u,int v){if(a[u].x>a[v].x&&a[u].y>a[v].y) return 1;if(a[u].x>a[v].y&&a[u].y>a[v].x) return 1;return 0;}int dp(int u){int i;if(vis[u]) return f[u];for(i=head[u];~i;i=e[i].next){int v=e[i].v;f[u]=max(f[u],dp(v));}f[u]+=a[u].z;vis[u]=1;return f[u];}int main(){int i,j,n,ans,Case=0;while(scanf("%d",&n)&&n){Case++;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));memset(f,0,sizeof(f));tot=0;ans=0;for(i=1;i<=n;i++){scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);a[i+n].x=a[i].x;  a[i+n].y=a[i].z;   a[i+n].z=a[i].y;a[i+n+n].x=a[i].y;  a[i+n+n].y=a[i].z;  a[i+n+n].z=a[i].x;}n=n+n+n;for(i=1;i<=n;i++){for(j=1;j<=n;j++){//cout<<a[i].x<<' '<<a[i].y<<"   "<<a[j].x<<' '<<a[j].y<<endl;if(check(i,j)){add(i,j);}}}for(i=1;i<=n;i++){ans=max(ans,dp(i));}printf("Case %d: maximum height = %d\n",Case,ans);}return 0;}

注意到这个图不会存在环,为无环有向图,可化为DAG上的最长路用dp求解。

原创粉丝点击