9-2 The Tower of Babylon uva437 (DP)

  题意:有n种立方体 每种都有无穷多个 要求选一些立方体叠成一根尽量高的柱子  (可以自行选择哪条边为高 )使得每个立方体的底面都严格小于他下方的立方体

为DAG模型

在任何时候 只有顶面的尺寸会影响到后续决策!!!! 

可以采用a,b来表示顶面尺寸   不过落实到dp会有一个问题: 因为a,b的值可能会很大  所以用(idx,k)来表示  idx为立方体的编号  k为第几条边作为高

dp[i][j]表示以 第i个立方体  第k条边为高(注意有序化)  作为最底下的立方体的最大高度

所以可以很轻松得出dp主过程:

 fo(i,n)
        fo(j,3)
        ans=max(ans,dp(i,j));

  就是枚举完所有的  

状态总数为 n  每个状态的决策有n个   所以 时间复杂度n2

#include<bits/stdc++.h>
using namespace std;
#define N 40
#define fo(i,n) for(int i=0;i<(n);i++)

int n;
int block[N][N];
int d[N][N];

void getdimensions(int *v,int i,int j)
{
    int idx=0;
    fo(a,3)
    if(a!=j)v[idx++]=block[i][a];
}

int dp(int i,int j)
{
    int& ans=d[i][j];//为了不用打d[i][j] 更加快
    if(ans>0)return ans;//避免重复计算
    ans=0;
    int v[2],v2[2];
    getdimensions(v,i,j);//读取该状态下 顶面的边长
    fo(a,n)
    fo(b,3)
     {
         getdimensions(v2,a,b);
         if(v[0]>v2[0]&&v[1]>v2[1])ans=max(ans,dp(a,b));
     }
     ans+=block[i][j];//改变了d[i][j]
     return ans;//又传递了值
}

int main()
{
    int cas=0;
    while(~scanf("%d",&n)&&n)
    {
        fo(i,n)
        {
            fo(j,3)scanf("%d",&block[i][j]);
            sort(block[i],block[i]+3);//注意一定要有序化 才能比较
        }
        memset(d,0,sizeof d);
        int ans=0;
        fo(i,n)//这里反过来也是一样的  因为是一个记忆化枚举的过程 所有的状态都会被枚举到
        fo(j,3)
        ans=max(ans,dp(i,j));
        printf("Case %d: maximum height = %d
",++cas,ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/bxd123/p/10462804.html