第一次不看题解1A掉DP,虽然是简单的2333.
题意概要:
有n类箱子,每类可以无限使用,求最高用这些箱子堆成多高塔?箱子可以任意旋转和翻转
限制:
1. 塔中每个箱子的底面的长和宽都要比它下面的箱子的长和宽严格的小
思路:
1. 我首先想到的是箱子可以无限用诶,难道没有一个限制吗?然后灵光一动,一类箱子如果不旋转和翻转,就只能放一个进塔中(由限制1), 那么可以旋转和翻转就最多6个啦,如果输入的是x y z,那么这六个就是:
x y z,
y z x,
x z y,
z x y,
y z x,
z y x。
也就是x y z的排列组合啦(23333)
所以把输入按以上处理就可以把箱子的无限化为有限
2.那么如何表示状态,我想到的首先就是dp[i][j], 用了 i个箱子并且用了第j个箱子时能达到的最大高度。
状态如何转移呢?
如果第k个箱子的底面比第j个箱子大
dp[i][j] = max(dp[i][j], dp[i-1][k] + node[j].z);
node[j]表示第j个箱子,z是它的高
为了方便处理我们用x对箱子排序这样只用遍历之前的箱子,而不用遍历所有箱子。
初始化时node[0]代表地,所以x, y为INF, z 为0。
得到代码如下:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define long long ll
#define INF 0x7fffffff
using namespace std;
struct Node{
int x, y, z;
}node[200];
int dp[200][200];
void assignTo(int i, int x, int y, int z){
node[i].x = x;
node[i].y = y;
node[i].z = z;
}
bool cmp(Node a, Node b){
return a.x > b.x;
}
int main(){
#ifdef _LOCAL_
freopen("C:\\Users\\Sorie\\Desktop\\debug\\in.txt","r",stdin);
freopen("C:\\Users\\Sorie\\Desktop\\debug\\out.txt","w",stdout);
#endif
int n;
int kase = 1;
while(cin >> n && n){
int cnt = 0;
int x, y, z;
node[0].x = node[0].y = INF;
node[0].z = 0;
memset(dp, 0 , sizeof dp);
for(int i = 1; i <=n ; i++){
scanf("%d %d %d", &x, &y, &z);
assignTo(++cnt, x, y, z);
assignTo(++cnt, y, x, z);
assignTo(++cnt, x, z, y);
assignTo(++cnt, z, x, y);
assignTo(++cnt, y, z, x);
assignTo(++cnt, z, y, x);
}
sort(node + 1, node + cnt + 1, cmp);
int ans = 0;
for(int i = 1; i <= cnt; i++){
for(int j = i; j <= cnt; j++){
for(int k = i - 1; k <= j; k++){
if(node[j].x < node[k].x && node[j].y < node[k].y){
dp[i][j] = max(dp[i-1][k]+node[j].z, dp[i][j]);
ans = max(ans, dp[i][j]);
}
}
}
}
cout << "Case " << kase++ << ": maximum height = ";
cout << ans << endl;
}
return 0;
}
我们可以发现,每次只用了前一个状态,所以可以把dp降成一维
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define long long ll
#define INF 0x7fffffff
using namespace std;
struct Node{
int x, y, z;
}node[200];
int dp[200];
void assignTo(int i, int x, int y, int z){
node[i].x = x;
node[i].y = y;
node[i].z = z;
}
bool cmp(Node a, Node b){
return a.x > b.x;
}
int main(){
#ifdef _LOCAL_
freopen("C:\\Users\\Sorie\\Desktop\\debug\\in.txt","r",stdin);
freopen("C:\\Users\\Sorie\\Desktop\\debug\\out.txt","w",stdout);
#endif
int n;
int kase = 1;
while(cin >> n && n){
int cnt = 0;
int x, y, z;
node[0].x = node[0].y = INF;
node[0].z = 0;
memset(dp, 0 , sizeof dp);
for(int i = 1; i <=n ; i++){
scanf("%d %d %d", &x, &y, &z);
assignTo(++cnt, x, y, z);
assignTo(++cnt, y, x, z);
assignTo(++cnt, x, z, y);
assignTo(++cnt, z, x, y);
assignTo(++cnt, y, z, x);
assignTo(++cnt, z, y, x);
}
sort(node + 1, node + cnt + 1, cmp);
int ans = 0;
for(int i = 1; i <= cnt; i++){
for(int j = i; j <= cnt; j++){
for(int k = i - 1; k < j; k++){
if(node[j].x < node[k].x && node[j].y < node[k].y){
dp[j] = max(dp[k]+node[j].z, dp[j]);
ans = max(ans, dp[j]);
}
}
}
}
cout << "Case " << kase++ << ": maximum height = ";
cout << ans << endl;
}
return 0;
}
欢迎指正, 以上