UVA 437_The Tower of Babylon

题意:

一堆石头,给定长宽高,每种石头均可以使用无数次,问这堆石头可以叠放的最高高度,要求下面的石头的长和宽分别严格大于上面石头的长和宽。

分析:

采用DAG最长路算法,由于长宽较大,不能直接用于表示状态,因此采用d[i][x]表示以第i块石头为最高点,以其第x个边为高所能达到的最大高度,其中i为石头标号,x代表长/宽/高,然后根据长宽高要求构造DAG,最后记忆化搜索求出最长路。

代码:

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int maxn = 0, ans = 0, n;
int y[35][4];
int G[35][4][35][4];
const int INF = 0x3fffffff;
int a[2],b[2], d[35][4];
int getDAG(int i, int k, int j, int m)
{
    if(k==1) a[0] = y[i][2], a[1] = y[i][3];
    else if(k==2) a[0] = y[i][3], a[1] = y[i][1];
    else a[0] = y[i][2], a[1] = y[i][1];

    if(m==1) b[0] = y[j][2], b[1] = y[j][3];
    else if(m==2) b[0] = y[j][3], b[1] = y[j][1];
    else b[0] = y[j][2], b[1] = y[j][1];

    sort(a,a+2);
    sort(b,b+2);

    return (a[0]>b[0]&&a[1]>b[1])?1:0;

}
int dp(int i, int k)
{
    int& ans = d[i][k];
    if(ans > 0) return ans;
    for(int j = 0; j < n; j++){
        for(int m = 1; m <= 3; m++){
            if(getDAG(j,m,i,k))  ans = max(ans, dp(j, m));
        }
    }
    ans += y[i][k];
    return ans;
}
int main (void)
{
    int a, b, c;
    cin>>n;
    int cnt = 1;
    while(n){
        maxn = 0;
        memset(d,0,sizeof(d));
        memset(G,0,sizeof(G));
        for(int i = 0; i < n; i++){
            cin>>a>>b>>c;
            y[i][1] = a; y[i][2] = b; y[i][3] = c;
        }
        for(int i = 0; i < n; i++)
                for(int k = 1; k <= 3; k++)
                    for(int j = 0; j < n; j++)
                        for(int m = 1; m <= 3; m++)
                                getDAG(i,k,j,m);

        for(int i = 0; i < n; i++)
            for(int k = 1; k <= 3; k++)
                maxn = max(maxn,dp(i, k));

        cout<<"Case "<<cnt<<": maximum height = "<<maxn<<endl;
        cin>>n;
        cnt++;
 }
}

很白痴的细节问题纠结了一下午,还是要细心!细心!

原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758848.html