Fork me on GitHub

动态规划2-----hdu1069

首先这道题目先要理解题目的意思。

用一些方块堆塔,给出的每种方块个数是无限的,只有满足长宽都小于下面一个方块的方块才能摆上去。

 

首先这道题需要一个转化。

每个方块有3个不同的面,每个面长宽交换,一共每个方块最多有6种情况。

X Y Z

1 2 3

2 1 3

3 1 2

1 3 2

2 3 1

3 2 1

如果长宽高有相同的部分还可以减少一些情况

 

然后对面积,长,宽,从小到大排序。

这步做完dp的准备才算完成。

 

 

下面分析dp部分。

 

如果不用dp,用贪心先试试,先把最大的面积放在下面,然后循环面积比他小的,如果满足长宽都小就摆上去,循环一遍摆完为止。

for(n->1)

{

        for(n-1->1)

        {

              max +=z;

        }

}

看上去貌似是可以的,但是其实是不行的,因为你摆了n-1之后,能不能摆n-3了,如果不能,你就不知道n-3和n-4的组合是不是比摆n-1要好了,所以贪心失败。

 

dp试试

从小到大,先摆最小的,然后用下一个,循环比所有他小的(之前已经摆好了),其中dp【】数据最优的,保存在当前dp【】数组中并且加上当前的方块高度。

 

状态转移方程

dp【now】 = max(for(now->1)循环中dp【】值最大的) + bolck【now】;

 

初始值

全部为0

 

下面给出dp的代码和贪心的代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>

using namespace std;
/*dp,hdu1069*/

int dp[500];//动态规划的数组

struct block
{
    int x;//
    int y;//
    int z;//
    int s;//面积
};

int cmp(const void * a, const void * b)
{
    struct block * p2 = (struct block *)a;
    struct block * p1 = (struct block *)b;
    
    if(p1->s != p2->s) 
        return p2->s - p1->s;
    else if(p1->x != p2->x)
        return p2->x - p1->x;
    else 
        return p2->y - p1->y;
}

int    main()
{
    int n;//方块个数
    int i,j;//循环变量
    int number=0;//记录可行方块数,一个方块最多有6钟可行方案
    int maxNumber=0;//记录结果
    int reslut=1;//记录次数
    int x,y,z;//用户输入
    int tempMax,tempX,tempY;//临时变量

    struct block blocks[500];//保存所有情况方块
    while (true)
    {
        cin>>n;
        if(n==0)
            break;

        number=0;
        for (i = 0; i < n; i++)
        {
            cin>>x>>y>>z;

            //记录6钟情况
            if(x==y&&y==z)
            {
                blocks[number].x = x;
                blocks[number].y = y;
                blocks[number].z = z;
                blocks[number].s = x*y;
                number++;
            }
            else
            {
                if(x==y)
                {
                    blocks[number].x = x;
                    blocks[number].y = y;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;
                }
                else
                {
                    blocks[number].x = x;
                    blocks[number].y = y;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;

                    blocks[number].x = y;
                    blocks[number].y = x;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;
                }
            

                if(x==z)
                {
                    blocks[number].x = x;
                    blocks[number].y = z;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;
                }
                else
                {
                    blocks[number].x = x;
                    blocks[number].y = z;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;

                    blocks[number].x = z;
                    blocks[number].y = x;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;
                }

            
                if(y==z)
                {
                    blocks[number].x = z;
                    blocks[number].y = y;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;
                }
                else
                {
                    blocks[number].x = z;
                    blocks[number].y = y;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;

                    blocks[number].x = y;
                    blocks[number].y = z;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;
                }
            }
        }

        //对于s-x-y小到大排序所有方块
        qsort(blocks, number, sizeof(block), cmp);

        maxNumber = 0;
        tempMax=0;
        dp[0] = blocks[0].z;
        maxNumber = dp[0];
        for (i = 1; i < number; i++)
        {
            dp[i]=blocks[i].z;
            tempMax=0;
            tempX=blocks[i].x;
            tempY=blocks[i].y;


            for (j = i-1; j >= 0; j--)
            {
                if(tempX > blocks[j].x && tempY > blocks[j].y)
                {
                    if(tempMax < dp[j])
                        tempMax=dp[j];
                }
            }

            dp[i] += tempMax;
            if(dp[i] > maxNumber)
                maxNumber=dp[i];
        }

        printf("Case %d: maximum height = %d\n",reslut,maxNumber);
        reslut++;
    }
    return 0;
}

贪心

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>

using namespace std;
/*贪心,失败,hdu1069*/

struct block
{
    int x;//
    int y;//
    int z;//
    int s;//面积
};

int cmp(const void * a, const void * b)
{
    struct block * p1 = (struct block *)a;
    struct block * p2 = (struct block *)b;
    
    if(p1->s != p2->s) 
        return p2->s - p1->s;
    else if(p1->x != p2->x)
        return p2->x - p1->x;
    else 
        return p2->y - p1->y;
}

int    main()
{
    int n;//方块个数
    int i,j;//循环变量
    int number=0;//记录可行方块数,一个方块最多有6钟可行方案
    int maxNumber=0;//记录结果
    int reslut=1;//记录次数
    int x,y,z;//用户输入
    int tempMax,tempX,tempY;

    struct block blocks[500];
    while (true)
    {
        cin>>n;
        if(n==0)
            break;

        number=0;
        for (i = 0; i < n; i++)
        {
            cin>>x>>y>>z;

            //记录6钟情况
            if(x==y&&y==z)
            {
                blocks[number].x = x;
                blocks[number].y = y;
                blocks[number].z = z;
                blocks[number].s = x*y;
                number++;
            }
            else
            {
                if(x==y)
                {
                    blocks[number].x = x;
                    blocks[number].y = y;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;
                }
                else
                {
                    blocks[number].x = x;
                    blocks[number].y = y;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;

                    blocks[number].x = y;
                    blocks[number].y = x;
                    blocks[number].z = z;
                    blocks[number].s = x*y;
                    number++;
                }
            

                if(x==z)
                {
                    blocks[number].x = x;
                    blocks[number].y = z;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;
                }
                else
                {
                    blocks[number].x = x;
                    blocks[number].y = z;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;

                    blocks[number].x = z;
                    blocks[number].y = x;
                    blocks[number].z = y;
                    blocks[number].s = x*z;
                    number++;
                }

            
                if(y==z)
                {
                    blocks[number].x = z;
                    blocks[number].y = y;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;
                }
                else
                {
                    blocks[number].x = z;
                    blocks[number].y = y;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;

                    blocks[number].x = y;
                    blocks[number].y = z;
                    blocks[number].z = x;
                    blocks[number].s = y*z;
                    number++;
                }
            }
        }

        qsort(blocks, number, sizeof(block), cmp);

        maxNumber = 0;
        tempMax=0;
        tempX=0;
        tempY=0;
        for (i = 0; i < number; i++)
        {
            tempMax=blocks[i].z;
            tempX=blocks[i].x;
            tempY=blocks[i].y;
            for (j = i+1; j < number; j++)
            {
                if(tempX > blocks[j].x && tempY > blocks[j].y)
                {
                    tempX=blocks[j].x;
                    tempY=blocks[j].y;
                    tempMax += blocks[j].z;
                }
            }
            if(tempMax > maxNumber)
                maxNumber=tempMax;
        }

        printf("Case %d: maximum height = %d\n",reslut,maxNumber);
        reslut++;
    }
    return 0;
}

经过实践,贪心可以满足前几组数据,但是最后一组数据就GG了

而且贪心和dp的效率在这里均为O(NlogN + N!)所以并没有快。

再一次证明dp确实很多时候比贪心好用。

但是其实最重要的是在dp之前对题目的分析,要把一个题目抽象到一组数,这个才是需要特别去考虑的事情,如果之前都想不到的话是肯定得不到最后的答案的。

posted @ 2016-04-10 01:00  LinkinStar  阅读(245)  评论(0编辑  收藏  举报