/*SE:wn------王宁*/
刘汝佳大神源码 && 我的AC代码(可能更简洁易懂)+ 我的前期思路、解说和总结 &&我前期的失败代码
// Rujia Liu
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define REP(i,n) for(int i = 0; i < (n); i++)
const int maxn = 30 + 5;
int n, blocks[maxn][3], d[maxn][3];
void get_dimensions(int* v, int b, int dim) {
int idx = 0;
REP(i,3) if(i != dim) v[idx++] = blocks[b][i];
}
int dp(int i, int j) {
int& ans = d[i][j];
if(ans > 0) return ans;
ans = 0;
int v[2], v2[2];
get_dimensions(v, i, j);
REP(a,n) REP(b,3) {
get_dimensions(v2, a, b);
if(v2[0] < v[0] && v2[1] < v[1]) ans = max(ans, dp(a,b));
}
ans += blocks[i][j];
return ans;
}
int main() {
int kase = 0;
while(scanf("%d", &n) == 1 && n) {
REP(i,n) {
REP(j,3) scanf("%d", &blocks[i][j]);
sort(blocks[i], blocks[i]+3);
}
memset(d, 0, sizeof(d));
int ans = 0;
REP(i,n) REP(j,3) ans = max(ans, dp(i,j));
printf("Case %d: maximum height = %d\n", ++kase, ans);
}
return 0;
}
/*SE:wn------王宁*/
/*------------失败的思路如下,失败的代码会放在最后面
让我们一起想想想,
让我们一起想想想~
首先,放在最上面的应该是让最小的两条边作为底座
让最长的那条边作为高,因为是最上面不需要再放东西了
否则,底变大,高变小,绝对划不来
所以是否可以将所有的x,y,z排好序?
x<y<z
然后对于第二高的,应该选取长和宽最接近且大于第一高的
否则对于不能满足大于条件的也不能作为其它的方块的底座
如果为了和上第一高的,我强行改变长和宽最接近但是不能满足
严格大于条件的长和宽,是否可以呢?如果不会影响到下一层绝对可以
即新x(i-1)<xi<x(i+1),y(i-1)<yi<y(i+1),当然这个变换要先将z变换成y
可是如果变换了导致下一层不能正常工作了呢,如果不完全大于下一层怎么办?
如果完全大于还好说,排到下一层去就好了
原则是底座最小,高度最大
底座不能撑起上一层更不能撑起下面的层,只能变换尺寸作为新的底座
插入到某个序列中——这样以后或许还可以抢救一下
---------实践之后失败的反思-----------
的确可以排序,可是排序的标准如何?问题还是出在不完全大于或者更加隐蔽的地方
中间还是会出现(可能,仅作猜测)一个严格逼近一个元素,另外一个则不一定,而另外一个
相对配对的那个对其他的砖更加友好……
---------看来还是要去dp---------------TAG,wait for me!
---------吼啊~ AC了呀~----------------
大佬的表示方式有点抽象and高级
所以我用了一维的来表示状态——因为按照高度来划分,其实
每种砖只有三种使用方式——while we assume that (x<y)
思路观看 紫书P263 嵌套矩形如何输出所有路径(DAG上的动态规划) 即可
这里是实现的代码网址
https://blog.csdn.net/JXUFE_ACMer/article/details/81448400
在这里学习到的有:
1.DAG编写实操
2.边获取答案边求值 for(i=0;i<3*n;i++) { magic=max ( magic,deepmind(i) ) ;}
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=35;
typedef struct info{
int x,y,z;
}block;
vector<block> v;
int dp[3*maxn];
bool vis[3*maxn];
int n;
int deepmind(int i){
if(vis[i]) return dp[i];
else{
vis[i]=1;
for(int j=0;j<3*n;j++){
if(v[j].x<v[i].x&&v[j].y<v[i].y){
dp[i]=max(dp[i],v[i].z+deepmind(j));
}
}
return dp[i];
}
}
int main()
{
int i,j,magic,a[3],sum,kase=0;
block t;
while(~scanf("%d",&n)&&n){
v.clear();
memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis));
for(i=0;i<n;i++){
scanf("%d%d%d",&a[0],&a[1],&a[2]);
sort(a,a+3);
t.x=a[0]; t.y=a[1]; t.z=a[2]; v.push_back(t); dp[v.size()-1]=t.z;
t.x=a[0]; t.y=a[2]; t.z=a[1]; v.push_back(t); dp[v.size()-1]=t.z;
t.x=a[1]; t.y=a[2]; t.z=a[0]; v.push_back(t); dp[v.size()-1]=t.z;
}
magic=-1;
for(i=0;i<3*n;i++) { magic=max ( magic,deepmind(i) ) ;}
printf("Case %d: maximum height = %d\n",++kase,magic);
}
return 0;
}
失败的版本:
#include<bits/stdc++.h>
using namespace std;
const int maxn=35;
typedef struct Info{
int x,y,z;
bool operator < (const Info &a) const{
if(a.y != y)
return a.y < y ;
if(a.x != x)
return a.x < x ;
}
}block;
int main()
{
int n,i,j,magic,a[3],sum;
priority_queue<block> pq;
block b,cmp,t;
while(~scanf("%d",&n)&&n){
for(i=1;i<=n;i++){
scanf("%d%d%d",&a[0],&a[1],&a[2]);
sort(a,a+3);
t.x=a[0]; t.y=a[1]; t.z=a[2]; pq.push(t);
t.x=a[0]; t.y=a[2]; t.z=a[1]; pq.push(t);
t.x=a[1]; t.y=a[2]; t.z=a[0]; pq.push(t);
}
printf("最顶上的这块砖x y z 分别等于%d %d %d\n",pq.top().x,pq.top().y,pq.top().z);
sum=pq.top().z; cmp=pq.top(); pq.pop();
while(!pq.empty()){
b=pq.top(); pq.pop();
printf("现在的这块砖x y z 分别等于%d %d %d\n",b.x,b.y,b.z);
if(b.x>cmp.x&&b.y>cmp.y) {sum+=b.z; cmp=b;}
}
printf("%d\n",sum);
}
return 0;
}