[动态规划] UVa437 巴比伦塔 (DAG的不确定起点终点的最长路)

题目

有n(n≤30)种立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子 (可以自行选择哪一条边作为高),使得每个立方体的底面长宽分别严格小于它下方立方体的底面长宽。

思路

DAG的不确定起点终点的最长路
1.状态及指标函数:d(i),在编号为i的立方体做塔的最底部,所能叠出的最高高度。(包括此立方体)
2.状态转移方程:

d ( i ) = m a x d ( j ) + i . h | ( j , i ) E

3.对于DAG的不确定起点终点的最长短路,没有递推做法,只能记忆化搜索,不需要设递归边界。算是比较简单的一种。

思路

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int maxn = 1000+100;
struct edge{
    int a, b, h;
}P[maxn];
int n, x, G[maxn][maxn], d[maxn];

// DAG不确定起点终点的最长短路不需要递归边界 
int dp(int i){
    int &ans = d[i];
    if (ans != -1) return ans;
    ans = P[i].h;
    _rep(j,1,x)
        if(G[j][i])
            ans = max(ans, dp(j) + P[i].h);
    return ans;
}

int main(){
    int kase = 0;
    while(scanf("%d",&n) == 1 && n){
        x=1; int a, b, c;
        _for(i,0,n){
            scanf("%d%d%d",&a,&b,&c);
            P[x].a = a, P[x].b = b, P[x++].h = c;
            P[x].a = a, P[x].h = b, P[x++].b = c;
            P[x].h = a, P[x].b = b, P[x++].a = c;
        }
        x--;

        memset(G, 0, sizeof(G));
        _rep(i,1,x)
            _rep(j,1,x)
                if(i!=j)
                    if ((P[i].a < P[j].a && P[i].b < P[j].b) || (P[i].a < P[j].b && P[i].b < P[j].a) )
                        G[i][j] = 1;

        memset(d,-1,sizeof(d));
        int maxans = 0;
        _rep(i,1,x)
            maxans = max(maxans, dp(i));
        printf("Case %d: maximum height = %d\n",++kase,maxans);
    }

    return 0;
} 

废话

1.DP只要想清楚思路,AC起题来好快啊

猜你喜欢

转载自blog.csdn.net/icecab/article/details/80740739