Uva 437 - The Tower of Babylon(DP)

题目链接 https://vjudge.net/problem/UVA-437

【题意】
       给定n种不同的立方体,每种立方体都有无穷多个,现在要用它们跌放在一起组成一个巴比伦塔,并且处在某个位置的立方体的底面长和宽一定严格小于它下面的那个立方体,你的任务是求出可以搭成的最高的塔高是多少?

【思路】
       把底面的长和宽以及对应的高当成一个状态结点,然后如果结点i能叠放在结点j之上那么就连接一条i到j的有向边,这样就形成了一个DAG,然后用动态规划求解带权值的最长路即可.

#include
using namespace std;

const int maxn = 35 * 3;

int n, cnt;
vector<int> g[maxn];
int dp[maxn];

struct Node {
    int r, c;
    int h;
    Node(int rr = 0, int cc = 0, int hh = 0) : r(rr), c(cc), h(hh) {}
}node[maxn];

int dfs(int u) {
    if (g[u].size() == 0) {
        return dp[u] = node[u].h;
    }
    if (dp[u] != -1) return dp[u];
    int ans = 0;
    for (int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i];
        ans = max(ans, node[u].h + dfs(v));
    }
    return dp[u] = ans;
}

int main() {
    int kase = 0;
    while (scanf("%d", &n) == 1 && n) {
        cnt = 0;
        for (int i = 0; i < n; ++i) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            node[cnt++] = Node(a, b, c);
            node[cnt++] = Node(a, c, b);
            node[cnt++] = Node(b, c, a);
        }
        for (int i = 0; i < cnt; ++i) g[i].clear();
        for (int i = 0; i < cnt; ++i) {
            for (int j = 0; j < cnt; ++j) {
                if (i == j) continue;
                if ((node[i].r < node[j].r && node[i].c < node[j].c) || (node[i].r < node[j].c && node[i].c < node[j].r)) {
                    g[i].push_back(j);//底面小的指向底面大的
                }
            }
        }
        memset(dp, -1, sizeof(dp));
        for (int i = 0; i < cnt; ++i) {
            if (-1 == dp[i]) dfs(i);
        }
        int ans = 0;
        for (int i = 0; i < cnt; ++i) {
            ans = max(ans, dp[i]);
        }
        printf("Case %d: maximum height = %d\n", ++kase, ans);
    }
    return 0;
}

你可能感兴趣的:(动态规划-----DAG上DP)