第九章例题 B - The Tower of Babylon UVA - 437

/*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;
}

猜你喜欢

转载自blog.csdn.net/JXUFE_ACMer/article/details/81483077