码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 437 The Tower of Babylon

时间:2019-03-17 23:17:20      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:highlight   void   for   要求   register   nbsp   map   rhs   邻接矩阵   

https://vjudge.net/problem/UVA-437

题目

有 $n$ 个立方体,每种都有无穷多个。要求选一些立方体摞成一根尽量高的柱子(可以自行选择哪一条边作为高),使得每个立方体的底面长款分别严格小于它下方立方体的长宽。输出最高高度。

题解

斗智题做了很久,最坑的是每次以为是和其他人AC的代码等价,结果还是WA了,甚至改了一整天还是WA,于是跳过第八章,开始做DP……

有向无环图的动态规划……

边权为高度,节点为地面正方形

因为可以旋转,所以要考虑每个立方体的个数,但是因为是无穷多个,所以就不管了= =

可以用集合栈计算机的编号的方法代替节点,事先建图(邻接矩阵,由于缓存作用,速度近似于前向星)

因为每次状态转移(把方块放上另外一个方块)不是独立的(结果会累加),因此不能用刷表法(“我为人人”),只能用填表法(“人人为我”)

因为顺序不确定,所以只能用记忆化搜索。如果要用递推,就必须将节点排序

因为状态有$\mathcal{O}(3n)$个,转移有$\mathcal{O}(3n)$种,时间复杂度为$\mathcal{O}(n^2)$

 

AC代码

#include<bits/stdc++.h>
using namespace std;

#define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define PER(r,x,y) for(register int r=(x); r>(y); r--)
#define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
#define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) (void)0
#endif

#define MAXN 37
#define MAXID 300

struct npii {
	int a,b;//a>=b
	npii(){}
	npii(int x, int y) {
		if(x>y) a=x,b=y;
		else a=y,b=x;
	}
	bool operator<(const npii&rhs) const {
		return a<rhs.a || (a==rhs.a && b<rhs.b);
	}
};

int n;
int arr[MAXN][3];
map<npii,int> mp;
npii st[MAXID];
int h[MAXID];
int dp[MAXID];
int id=0;
inline bool vali(int i, int j) {
	return st[i].a<st[j].a && st[i].b<st[j].b;
}
bool E[MAXID][MAXID];
inline int solve(int x) {
	if(dp[x]>=0) return dp[x];
	int ans=h[x];
	REP(i,0,id) {
		if(E[x][i]) {
			ans = max(ans, solve(i)+h[x]);
		}
	}
	return dp[x]=ans;
}
int main() {
	int kase=0;
	while(~scanf("%d", &n) && n) {
		kase++;
		id=0;
		mp.clear();
		memset(dp,-1,sizeof dp);
		REP(i,0,n) {
			scanf("%d%d%d", &arr[i][0], &arr[i][1], &arr[i][2]);
			#define OP(x,y,z) if(mp.count(npii(arr[i][x],arr[i][y]))==0) {mp[npii(arr[i][x],arr[i][y])]=id;st[id]=npii(arr[i][x],arr[i][y]);h[id]=arr[i][z];id++;}
			OP(0,1,2); OP(1,2,0); OP(0,2,1);
			#undef OP
		}
		memset(E,0,sizeof E);
		REP(i,0,id) {
			REP(j,0,id) {
				if(vali(i,j)) {
					E[i][j]=1;
				}
			}
		}
		int maxx=0;
		REP(i,0,id) {
			maxx = max(maxx,solve(i));
		}
		printf("Case %d: maximum height = %d\n", kase, maxx);
	}
	return 0;
}

做水题一时爽,一直做水题一直爽= =

UVA 437 The Tower of Babylon

标签:highlight   void   for   要求   register   nbsp   map   rhs   邻接矩阵   

原文地址:https://www.cnblogs.com/sahdsg/p/10549479.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!