题目大意:给出塔的长宽高(立方体),每个塔长宽高可任意且无限用,要求将所以可能的塔堆起来,题意要求上边的塔的长宽必须分别小于下面的长宽。
最后求出满足题意的塔的最大高度。
解题策略:每个立方体,长宽高因为可以互换,所以可以将每一个立方体可拓展为3! = 6种立方体,全部存储,并按照底面积降序排列,然后以题意要求求出变形LIS。
详见注释。
/*
UVA 437 The Tower of Babylon
AC by J.Dark
ON 2013/4/7
Time 0.012s
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;
const int maxn = 200;
/
struct St{
int length, width, height;
int area;
}Stone[maxn];
int stCount=0, count1=0, testCase, maxHeight;
/
void Input(){
count1++;
int temp[3];
//默认塔的底座为底面积无穷大,但高度为0
//用来使第一个塔可以进入O(n2)算法
Stone[0].length = INT_MAX;
Stone[0].width = INT_MAX;
Stone[0].height = 0;
Stone[0].area = INT_MAX;
//拓展一个塔为六个塔
for(int i=1; i<=testCase; i++){
cin >> temp[0] >> temp[1] >> temp[2];
Stone[++stCount].length = temp[0];
Stone[stCount].width = temp[1];
Stone[stCount].height = temp[2];
Stone[stCount].area = temp[0]*temp[1];
//next_permutation为STL里的全排列函数,用途为形成当前排列的下一个全排列,若存在返回真,否则假
//注意当输入“3 2 1”,该函数不再生成全排列,但返回最小的排列即“1 2 3”
while(next_permutation(temp, temp+3)); //生成最小的全排列
while(next_permutation(temp, temp+3)) //拓展一塔为六塔,长宽高互换为新塔,即3!种
{
Stone[++stCount].length = temp[0];
Stone[stCount].width = temp[1];
Stone[stCount].height = temp[2];
Stone[stCount].area = temp[0]*temp[1];
}
}
}
int cmp(St x, St y){
return x.area > y.area;
}
void Solve(){
//按底面积降序排列
sort(Stone+1, Stone+stCount+1, cmp);
int Height[maxn]; //到当前元素为止,塔的最大高度
for(int i=0; i<=stCount; i++) Height[i] = 0;
for(int i=0; i<=stCount; i++){
for(int j=0; j<i; j++){
//判断i是否可以底面积比i大的塔之上
if(Stone[i].length < Stone[j].length && Stone[i].width < Stone[j].width){
if(Height[j]+Stone[i].height > Height[i]){ //如果可以放上去
Height[i] = Height[j]+Stone[i].height; //更新
}
}
}
}
maxHeight = 0;
for(int i=1; i<=stCount; i++)
maxHeight = max(maxHeight, Height[i]);
printf("Case %d: maximum height = %d\n", count1, maxHeight);
stCount = 0;
}
/
int main(){
while(cin >> testCase && testCase)
{
Input();
Solve();
}
//system("pause");
return 0;
}
附朱神牛的范例代码,用priority_queue(优先队列),并且一个塔拓展三个塔,以高度为拓展条件。
/*
UVa437 - The Tower of Babylon
Solved by Guojin Zhu
Run Time 0.008s
AC on April 5, 2013
*/
#include<iostream>
#include<queue>
#include<algorithm>
#include<climits>
using namespace std;
//
struct Block{
int longBase;
int shortBase;
int height;
Block(int a = 0, int b = 0, int c = 0){longBase = a; shortBase = b; height = c;}
friend bool operator < (Block b1, Block b2){// cannot put b1 onto b2
return b1.longBase < b2.longBase;
}
friend bool operator > (Block b1, Block b2){// can put b2 onto b1
return (b1.longBase > b2.longBase) && (b1.shortBase > b2.shortBase);
}
};
class BabylonTower{
private:
priority_queue<Block> sequence; //blocks sorted by < from large to small
int maxHeight;
public:
void initial();
void readCase(int);
void computing();
void outResult(int);
};
void BabylonTower::initial(){
while(!sequence.empty()){//clear the sequence
sequence.pop();
}
maxHeight = 0;
}
void BabylonTower::readCase(int n){
int x, y, z;
while(n--){
cin >> x >> y >> z;
sequence.push(Block(max(x, y), min(x, y), z));
sequence.push(Block(max(y, z), min(y, z), x));
sequence.push(Block(max(z, x), min(z, x), y));
}
}
void BabylonTower::computing(){
queue<Block> q;
Block b, cur;
int qsize, mHeight;
q.push(Block(INT_MAX, INT_MAX, 0)); //for the sentinel
while(!sequence.empty()){//BFS
//cout << sequence.top().longBase << ' ' << sequence.top().shortBase << ' ' << sequence.top().height << endl;
b = sequence.top();
sequence.pop();
qsize = q.size();
mHeight = b.height;
while(qsize--){
cur = q.front();
q.pop();
q.push(cur);
if(cur > b){
mHeight = max(mHeight, cur.height + b.height);
}
}
b.height = mHeight; // new height
q.push(b);
}
while(!q.empty()){
maxHeight = max(maxHeight, q.front().height);
q.pop();
}
}
void BabylonTower::outResult(int c){
cout << "Case " << c << ": maximum height = " << maxHeight << endl;
}
//
int main(){
BabylonTower bt;
int n, c = 1;
while((cin >> n) && n){
bt.initial();
bt.readCase(n);
bt.computing();
bt.outResult(c++);
}
return 0;
}
/*
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
-------------
OUTPUT
Case 1: maximum height = 40
Case 2: maximum height = 21
Case 3: maximum height = 28
Case 4: maximum height = 342
*/