zoukankan      html  css  js  c++  java
  • 动态规划:巴比伦塔

      做了一道ZOJ上的题目,发现是一道经典原题的改编(只改了题目背景。。数据都一样)。

      ZOJ Problem Set - 1093 解题报告

      原题地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1093

      题目分类:动态规划

      题目大意:有n种木块,每种都是无限提供,木块可以随意摆放(即每条边都可能为高)。当某一块木块的长和宽都小于下面的木块时,才能叠在上面。要求最高能叠多高。

      恰好在做这一题的时候,看了看书,发现了一道例题跟这题一模一样——巴比伦塔。所以我把题目原型摆出来。

      巴比伦塔(The Tower of Babylon,UVa 437)http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=19214

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

      每个人有每个人的写法,或许有比我的代码更简洁的,不过我只讲我的思路,我觉得简单易懂的。

      每一种木块都有三种摆放方式,因为有三条边。用b[n][3]来储存输入的每个木块的长宽高,再用a[n*3][3]储存所有的情况。刚开始我想先排序然后判断可以叠加就一直往上加,然后发现答案是错的。这样是贪心,但不能用贪心,因为每选一种木块都会影响到后面的所有木块。我们要分析问题的状态。在这3*n种情况中,我们用d[i]来表示以第 i 块木块为顶层的最大高度。因为能放在第 i 块木块下方的情况可能不止一种,当然也可能没有,所以我又用了一个put[i][j]表示第 i 块木块能否放在第 j 块木块上。于是 d[i] = max{a[i],d[j]+a[i] | 0<=j<3*n,put[i][j] = 1} 。这样就得到了状态转移方程。其实每次做动态规划的关键就是几点:1、状态和状态转移方程。2、做记录。 做记录就是我们这里的d[i],这样每个方案只会计算一次,不会重复计算,这才体现了动态规划的优点。最终我的所求的最大高度 maxheight = max {d[i] | 0<=i<3*n}。

      把样例测试过了之后就一遍AC了。代码如下:http://paste.ubuntu.com/15332896/

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 int a[91][3];        //所有木块可能
     7 int put[91][91];    //put[i][j]表示i能放在j上
     8 int d[91];            //d[i]表示以第i个木块为顶层的最大高度
     9 int n;
    10 int dp(int i)        //以第i块木板为顶的最大高度
    11 {
    12     int j;
    13     int &ans = d[i];
    14     if(ans > 0)    return ans;
    15     ans = a[i][2];
    16     for(j=0;j<3*n;j++)
    17     {
    18         if(put[i][j])
    19         {
    20             ans = max(ans,dp(j) + a[i][2]);
    21         }
    22     }
    23     return ans;
    24 }
    25 void output(int times)
    26 {
    27     int i,j,height = 0,h = 0;
    28     for(i=0;i<3*n;i++)
    29     {
    30         for(j=0;j<3*n;j++)
    31         {
    32             if((a[i][0] < a[j][0] && a[i][1] < a[j][1]) || (a[i][0] < a[j][1] && a[i][1] < a[j][0]))
    33             {
    34                 put[i][j] = 1;
    35             }
    36         }
    37     }
    38     for(i=0;i<3*n;i++)
    39     {
    40         h = dp(i);
    41         height = max(h,height);
    42     }
    43     cout<<"Case "<<times<<": maximum height = "<<height<<endl;
    44 }
    45 int main()
    46 {
    47     int block[33][3];
    48     int i,c,time = 1;
    49     while(cin>>n && n)
    50     {
    51         c = -1;
    52         for(i=0;i<n;i++)
    53         {
    54             cin>>block[i][0]>>block[i][1]>>block[i][2];
    55             a[++c][0] = block[i][0];
    56             a[c][1] = block[i][1];
    57             a[c][2] = block[i][2];
    58             a[++c][0] = block[i][0];
    59             a[c][1] = block[i][2];
    60             a[c][2] = block[i][1];
    61             a[++c][0] = block[i][1];
    62             a[c][1] = block[i][2];
    63             a[c][2] = block[i][0];
    64         }
    65         //cout<<"可能情况:"<<endl;
    66         //for(i=0;i<3*n;i++)
    67         //    cout<<"i="<<i<<": "<<a[i][0]<<" "<<a[i][1]<<" "<<a[i][2]<<endl;
    68         memset(d,0,sizeof(d));
    69         memset(put,0,sizeof(put));
    70         output(time);
    71         time++;
    72     }
    73 }
  • 相关阅读:
    用Creator实现一个擀面的效果
    游戏开发中的多语言处理
    Docker(六)容器数据卷
    Docker(五)Docker镜像讲解
    Docker(四)Docker镜像安装
    Docker(三)Docker常用命令
    Docker(二)Docker配置
    nginx 与 tomcat 组合搭建web服务
    Zookeeper 使用
    tomcat-manager 设置
  • 原文地址:https://www.cnblogs.com/GodA/p/5257707.html
Copyright © 2011-2022 走看看