ACM: 动态规划题 poj 2241

来源:互联网 发布:mac下面的图标怎么换掉 编辑:程序博客网 时间:2024/05/22 01:37
                                   The Tower of Babylon
Description
Perhaps you haveheard of the legend of the Tower of Babylon. Nowadays many detailsof this tale have been forgotten. So now, in line with theeducational nature of this contest, we will tell you the wholestory:
The babylonians had n types of blocks, and an unlimited supply ofblocks of each type. Each type-i block was a rectangular solid withlinear dimensions (xi, yi, zi). A block could be reoriented so thatany two of its three dimensions determined the dimensions of thebase and the other dimension was the height.
They wanted to construct the tallest tower possible by stackingblocks. The problem was that, in building a tower, one block couldonly be placed on top of another block as long as the two basedimensions of the upper block were both strictly smaller than thecorresponding base dimensions of the lower block. This meant, forexample, that blocks oriented to have equal-sized bases couldn't bestacked.

Your job is to write a program that determines the height of thetallest tower the babylonians can build with a given set ofblocks.

Input

The input willcontain one or more test cases. The first line of each test casecontains an integer n,
representing the number of different blocks in the following dataset. The maximum value for n is 30.
Each of the next n lines contains three integers representing thevalues xi, yi and zi.
Input is terminated by a value of zero (0) for n.

Output

For each test case,print one line containing the case number (they are numberedsequentially starting from 1) and the height of the tallestpossible tower in the format "Case case: maximum height =height"

Sample Input

1
10 20 30
2
6 8 10
5 5 5
7
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
5
31 41 59
26 53 58
97 93 23
84 62 64
33 83 27
0

Sample Output

Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342

题意: 给出每种积木的长宽高, 并且每块积木的个数不定, 现在要你计算出积木堆起来最大高度,

     要求下面一块积木的长宽严格大于上面一块积木的长宽.

解题思路:

         1.一开始进入一个误区了, 以为积木要按照顺序拿取.(受黑书题目的影响, 也受到启发).

        2. 随机拿去,只要高度最高即可.

         3.动态规划状态dp[i]: 表示第i中决策时积木堆的最大高度.

        4. 状态转移方程

           问题解析:

           先给与决策的构建: 每种积木有三种顶面的决策. add(a,b,c); add(b,c,a); add(c,a,b);

                             即每种积木可以创建出三种决策.

         if((g[i][0]> g[j][0] && g[i][1]> g[j][1]) || (g[i][0] > g[j][1]&& g[i][1] >g[j][0]))

                  dp[i] = dp[j]+g[i][2];

         即决策i向决策j进行时, 满足的条件是上一个决策的顶面要小于当前选择的决策的低面.

          5.记忆化搜索可以高效进行求解.

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 31
const int INF = (1<<29);

int n;
int g[MAX*3][3];
int dp[MAX*3];
int num;

inline int max(int a,int b)
{
 return a > b ? a : b;
}

void add(int a,int b,int c)
{
 num++;
 g[num][0] = a;
 g[num][1] = b;
 g[num][2] = c;
}

int DP(int i)
{
 if(dp[i] != -1) return dp[i];
 if(i > num) return 0;
 int ans = 0;
 for(int j = 1; j <= num;++j)
 {
  if( (g[i][0] >g[j][0] && g[i][1] >g[j][1]) || (g[i][0] > g[j][1]&& g[i][1] >g[j][0]) )
   ans =max(ans,DP(j)+g[j][2]);
 }
 dp[i] = max(dp[i],ans);
 return dp[i];
}

int main()
{
// freopen("input.txt","r",stdin);
 int k = 1;
 int i, j;
 while(scanf("%d",&n) != EOF&& n != 0)
 {
  int a, b, c;
  num = 0;
  g[0][0] = g[0][1] = g[0][2] =INF;
  for(i = 0; i <n; ++i)
  {
   scanf("%d %d%d",&a,&b,&c);
   add(a,b,c);
   add(b,c,a);
   add(c,a,b);
  }
  memset(dp,-1,sizeof(dp));
  int result = DP(0);
  printf("Case %d: maximum height= %d\n",k++,result);
 }

 return 0;
}

 

0 0
原创粉丝点击