【动态规划】The Tower of Babylon 巴比伦塔

Description

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

Inout sample

1
10 20 30
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0

Output sample

Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342

————————————————分割の线————————————————

分析

根据题意,上方立方体的底面积应当小于下方立方体的底面积,又因为每个立方体有无数个,所以可以得到一条结论

一个立方体下方的摆放不影响其上方的立方体摆放。

由此可以设f[i][j]表示到立方体i时以第j条边作为高所能达到的最高值。(a[i][j]表示第i个立方第j条边的高度)

于是就开始了对于状态转移方程的苦思冥想,
……
……
果然还是用记忆化搜索更简单

代码如下

#include
#include
#include
#include
using namespace std;
int f[2000][3],n;//f[i][j]表示以第i个立方体为底以第j条边为高的最大高度
int a[2000][3],cnt=0;
int dp(int u,int hight)
{
    if(f[u][hight]>=0) return f[u][hight];
    f[u][hight]=a[u][hight];//高至少为自己
    int x,y,ux,uy;//x,y为第u个立方体的长和宽
    if(hight==0)
        x=a[u][1],y=a[u][2];
    if(hight==1)
        x=a[u][0],y=a[u][2];
    if(hight==2)
        x=a[u][0],y=a[u][1];
    for(int i=1;i<=n;i++)
        for(int k=0;k<3;k++)
        {//ux,uy为第i个立方体的长和宽
            if(k==0)
                ux=a[i][1],uy=a[i][2];
            if(k==1)
                ux=a[i][0],uy=a[i][2];
            if(k==2)
                ux=a[i][0],uy=a[i][1];
            if(x>ux&&y>uy||y>ux&&x>uy)//如果满足长和宽严格小于的这个基本事实,则向下进行搜索
                if(f[u][hight]//保留最佳答案
    }
    return f[u][hight];
}
int main()
{
    scanf("%d",&n);
    while(n>0)//如果n不为0,则再次循环
    {
        cnt++;//记录循环次数
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);//读入三条边
        memset(f,-1,sizeof(f));//初始化f,默认f未做过
        for(int i=1;i<=n;i++)
            for(int k=0;k<3;k++)
            {
                f[i][k]=dp(i,k);//请完成第一步,剩下的都交给记忆化搜索吧
            }
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int k=0;k<3;k++)
                if(f[i][k]>ans) ans=f[i][k];//无脑枚举,求最大值
        printf("Case %d: maximum height = %d\n",cnt,ans);//按规则输出答案
        scanf("%d",&n);//再次读入n
    }
    return 0;
}

你可能感兴趣的:(HG集训,入门经典dp)