动态规划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之前对题目的分析,要把一个题目抽象到一组数,这个才是需要特别去考虑的事情,如果之前都想不到的话是肯定得不到最后的答案的。

时间: 2024-10-10 10:34:24

动态规划2-----hdu1069的相关文章

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

活动选择的贪心算法与动态规划(未完成)

// greedy_algorithm.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; #define NofActivity 11 int c[NofActivity + 1][NofActivity + 1]; int reme[NofActivity + 1][NofActivity + 1]; //活动的

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

Beauty Of algorithms(七)动态规划 钢条分割 矩阵链乘 最长公共子序列 最优二叉树

1.动态规划                动态规划的方法与方法类似,英文"dynamic programming",这里的programming不是程序的意思,而是一种表格法.都是通过组合子问题的解来解决原问题,分治方法将划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来求出原问题的解.与之相反动态规划应用于子问题的重叠情况,即不同的子问题具有公共的子问题,子问题的求解是递归进行 的,将其划分为更小的子问题,动态规划,每个子问题只求解一次,将其保存在表格中,从而无需每次求

Hdoj 1176 免费馅饼 【动态规划】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26110    Accepted Submission(s): 8905 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

pat 1068 动态规划/Fina More Conis

1068. Find More Coins (30) Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special re

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取