DP 动态规划 Problem E 1005 最大递增子序列

Problem E  ID:1005


简单题意:提供无限个若干种长为xi,宽为yi,高为zi的砖块,砖块可以调整方向(如长也可以为宽或高)。若一个砖块的长和宽分别比另一个砖块的长和宽小,则此砖块可以垒在后一个砖块的上面。问:最大可以垒多高?

解题思路形成过程:实际上是一种条件稍复杂些的最大递增子序列问题。
            每种砖块的高共有三种情况(*3),其中每种情况分别对应两种长和宽(*2),所以每个砖块共有6种摆放方式,n个砖块有6*n种摆放方式。
            每输入一种砖块类型,将对应的6种长、宽、高储存到相应的数组中。
            按照砖块长的大小由小到大进行排序,如果两个砖块的长相同,则按照砖块宽的大小由小到大进行排序。
            从第一个砖块开始按照求最大递增子序列问题的DP方式进行遍历,遍历至最后一个砖块,即可求得最大值。

感想:看似比最基本的最大递增子段和问题要复杂很多,但耐下心来就会发现,只是多了对数组进行存储和排序操作,DP的部分多一些思考罢了。重要的是要看出问题需要用什么方式来进行解决,如何抽象化。

代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int n;
int x[181],y[181],z[181];
int dp[181];
void exch_1(int i)
{
    x[i+1]=x[i];
    y[i+1]=z[i];
    z[i+1]=y[i];
}
void exch_2(int i)
{
    x[i+2]=y[i];
    y[i+2]=x[i];
    z[i+2]=z[i];

    x[i+3]=y[i];
    y[i+3]=z[i];
    z[i+3]=x[i];
}
void exch_3(int i)
{
    x[i+4]=z[i];
    y[i+4]=x[i];
    z[i+4]=y[i];

    x[i+5]=z[i];
    y[i+5]=y[i];
    z[i+5]=x[i];
}
void cmp()
{
    for(int i=1;i<6*n;++i)
        for(int j=0;j<i;++j)
        {
            if(x[j]>x[i])
            {
                int t=x[i];
                x[i]=x[j];
                x[j]=t;
                t=y[i];
                y[i]=y[j];
                y[j]=t;
                t=z[i];
                z[i]=z[j];
                z[j]=t;
            }
            else if(x[j]==x[i])
                if(y[j]>y[i])
                {
                    int t=y[i];
                    y[i]=y[j];
                    y[j]=t;
                    t=z[i];
                    z[i]=z[j];
                    z[j]=t;
                }
        }
}
int DP()
{
    int cmax=z[0];
    dp[0]=z[0];
    for(int i=1;i<6*n;++i){
        dp[i]=z[i];
        for(int j=0;j<i;++j)
        {
            if(x[j]<x[i]&&y[j]<y[i])
                if(dp[j]+z[i]>dp[i]){
                    dp[i]=dp[j]+z[i];
                }
        }
        if(dp[i]>cmax)
            cmax=dp[i];
    }
    return cmax;
}
int main()
{
    freopen("1.txt","r",stdin);
    int m=1;
    while(scanf("%d",&n)!=EOF&&n)
    {
        for(int i=0;i<6*n;i+=6){
            scanf("%d %d %d",&x[i],&y[i],&z[i]);
            exch_1(i);
            exch_2(i);
            exch_3(i);
        }
        cmp();
        int t=DP();
        printf("Case %d: maximum height = %d\n",m++,t);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值