UVA 437 巴比伦塔 DAG模型+记忆化

UVA 437 巴比伦塔
题目大意:
有n(n<=30) 种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子(任意一条边都可以作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。

DAG模型————无固定终点的最长路
详情请见算法竞赛入门经典(第二版) Page269

原创代码,三种情况分得很清楚。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

int n,a[305],b[305],c[305];
int d[305][4];
int pan1(int i, int j){
    if(b[i]<b[j] && c[i]<c[j]) return 1;
    if(b[i]<c[j] && c[i]<b[j]) return 1;
    return 0;
}
int pan2(int i, int j){
    if(a[i]<b[j] && c[i]<c[j]) return 1;
    if(a[i]<c[j] && c[i]<b[j]) return 1;
    return 0;
}
int pan3(int i, int j){
    //printf("ok");
    if(a[i]<b[j] && b[i]<c[j]) return 1;
    if(a[i]<c[j] && b[i]<b[j]) return 1;
    return 0;
}
int pan4(int i, int j){
    if(b[i]<a[j] && c[i]<c[j]) return 1;
    if(b[i]<c[j] && c[i]<a[j]) return 1;
    return 0;
}
int pan5(int i, int j){
    if(b[i]<a[j] && c[i]<b[j]) return 1;
    if(b[i]<b[j] && c[i]<a[j]) return 1;
    //printf("pp");
    return 0;
}
int pan6(int i, int j){
    if(a[i]<a[j] && c[i]<c[j]) return 1;
    if(a[i]<c[j] && c[i]<a[j]) return 1;
    return 0;
}
int pan7(int i, int j){
    if(a[i]<a[j] && c[i]<b[j]) return 1;
    if(a[i]<b[j] && c[i]<a[j]) return 1;
    return 0;
}
int pan8(int i, int j){
    if(a[i]<a[j] && b[i]<c[j]) return 1;
    if(a[i]<c[j] && b[i]<a[j]) return 1;
    return 0;
}
int pan9(int i, int j){
    if(a[i]<a[j] && b[i]<b[j]) return 1;
    if(a[i]<b[j] && b[i]<a[j]) return 1;
    return 0;
}


int dp(int i, int op){
    if(op == 0){
        if(d[i][op] != a[i]) return d[i][op];
        //printf("kk");
        for(int j=1;j<=n;j++){
            if(pan1(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + a[i]);// i bc; j bc
            if(pan4(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + a[i]);//i-->bc ; j-->ac
            if(pan5(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + a[i]);//i-->bc;j-->ab
            
            
        }
    }
    if(op == 1){
        if(d[i][op] != b[i]) return d[i][op];
        
        for(int j=1;j<=n;j++){
            if(pan2(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + b[i]);//i ac ; j bc
            if(pan6(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + b[i]);//i-->ac ; j-->ac
            if(pan7(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + b[i]);//i-->ac;j-->ab
        }
    }
    if(op == 2){
        if(d[i][op] != c[i]) return d[i][op];
        for(int j=1;j<=n;j++){
            if(pan3(i,j)) d[i][op] = max(d[i][op] , dp(j,0) + c[i]);//i ab; j bc
            if(pan8(i,j)) d[i][op] = max(d[i][op] , dp(j,1) + c[i]);//i-->ab ; j-->ac
            if(pan9(i,j)) d[i][op] = max(d[i][op] , dp(j,2) + c[i]);//i-->ab;j-->ab
        }
    }
    //printf("kk");
    return d[i][op];
}


int main(){
    int num=0;
    while(scanf("%d",&n)){
        num++;
        if(n==0) break;
        int ans=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
        }
        for(int i=1;i<=n;i++){
            d[i][0]=a[i];
            d[i][1]=b[i];
            d[i][2]=c[i];
        }
            
        for(int i=1;i<=n;i++){
            //printf("%d ",dp(i,2));
            ans = max(ans,max(max(dp(i,0),dp(i,1)),dp(i,2)));
        }
        
        printf("Case %d: maximum height = %d\n",num,ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值