题意:
给你n种木块,木块的个数不限,规范木块堆积的规则,底下的木块的长、宽必须都大于上面木块的长宽。现在问你最高能叠的高度
解法:
这个题没想通是因为,每种木块分成 底、高来看的话,有三种状态( 为什么底可以不用细分?因为底的两边可以互换,相当于一个长方体,转了一下 ,因此底看成整体),那我们需要在一个单位上保存三种状态。那么在找子结构的时候,就需要判断子结构的某状态是可用的,需要很多标记,况且自身也是可以堆起来的。
正解:
多重背包思维:每种状态转换成多种状态,那么就拆分开来 。 例如本题,输入一种木块的参数,我们构造出三块固定 底 高 的木块,这样就好做了。
代码:
/*
被教育了 , 一种木块 可以转换成多种状态, 而且取木块的次数不限的时候, 可以把各个状态当成一个新的木块,
多重背包思维。小本本记下了*/
#include <iostream>
#include <bits/stdc++.h>using namespace std;
const int maxn = 35 ;
int dp[maxn*3];struct Node
{int l,r,h,area;}node[maxn*3];bool cmp(Node a, Node b)
{return a.area > b.area;
}
int main()
{int n;int cas = 1;while(scanf("%d",&n) && n){for(int i=1;i<=3*n;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);node[i].l = a, node[i].r = b, node[i].h = c;node[i].area = a*b;i++;node[i].l = a, node[i].r = c, node[i].h = b;node[i].area = a*c;i++;node[i].l = b, node[i].r = c, node[i].h = a;node[i].area = b*c;}sort(node+1,node+1+3*n,cmp);int ans = 0;for(int i=1;i<=3*n;i++){int tmp = 0;for(int j=1;j<i;j++) //{if( (node[i].r<node[j].r && node[i].l < node[j].l) || (node[i].r< node[j].l && node[i].l < node[j].r) )if(dp[j] > tmp)tmp = dp[j];}dp[i] = tmp + node[i].h;ans = max(ans,dp[i]);}printf("Case %d: maximum height = %d\n",cas++,ans);}}