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 }
  • 相关阅读:
    OutputCache 缓存key的创建 CreateOutputCachedItemKey
    Asp.net Web Api源码调试
    asp.net mvc源码分析DefaultModelBinder 自定义的普通数据类型的绑定和验证
    Asp.net web Api源码分析HttpParameterBinding
    Asp.net web Api源码分析HttpRequestMessage的创建
    asp.net mvc源码分析ActionResult篇 RazorView.RenderView
    Asp.Net MVC 项目预编译 View
    Asp.net Web.config文件读取路径你真的清楚吗?
    asp.net 动态创建TextBox控件 如何加载状态信息
    asp.net mvc源码分析BeginForm方法 和ClientValidationEnabled 属性
  • 原文地址:https://www.cnblogs.com/GodA/p/5257707.html
Copyright © 2011-2022 走看看