• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

uva 437 巴比伦塔(DAG上dp)

巴比伦塔

紫书P269 看完紫书,终于可以自己写一个dp了 😃

【题目链接】巴比伦塔

【题目类型】DAG上dp

&题意:

有n种立方体 n<=30,每种有无穷个,要求选一些立方体摞成一根尽量高的柱子,上面的立方体长和宽必须严格小于下面的。

&题解:

看紫书前,我的想法:
这题就把所有的3种情况排个序啊,根据长和宽排,之后累计加高,就好了。

看紫书后,我的想法:
这是一个二元关系,而且没有环,又范围很小,所以用邻接矩阵建图,也就转化成DAG上的最长路径了。

差距:
之前的想法太幼稚,没有考虑到这样的情况:2 9 10之后是3 5 100 如果按照我之前的想法,那么我一定会用了长2 宽9 高10这个立方体,之后显然 高为100这个就用不到了,这明显不是最优的。
如果这块想通了,那么之后的想法也就没问题了:所以我们现在要做的是时时刻刻更新最大值,所以就是递归dp。

这题让我知道了,对于你并不知道这一步应该选择什么的时候,而且还没有规律,那么你也许就可以用dp,因为dp可以随时更新出你想要的东西。

【时间复杂度】O(n^2)

&代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
#define cle(a,val) memset(a,(val),sizeof(a))
#define SI(N) scanf("%d",&(N))
#define SII(N,M) scanf("%d %d",&(N),&(M))
#define SIII(N,M,K) scanf("%d %d %d",&(N),&(M),&(K))
#define rep(i,b) for(int i=0;i<(b);i++)
#define rez(i,a,b) for(int i=(a);i<=(b);i++)
#define red(i,a,b) for(int i=(a);i>=(b);i--)
const ll LINF = 0x3f3f3f3f3f3f3f3f;
#define PU(x) puts(#x);
#define PI(A) cout<<(A)<<endl;
#define DG(x) cout<<#x<<"="<<(x)<<endl;
#define DGG(x,y) cout<<#x<<"="<<(x)<<" "<<#y<<"="<<(y)<<endl;
#define DGGG(x,y,z) cout<<#x<<"="<<(x)<<" "<<#y<<"="<<(y)<<" "<<#z<<"="<<(z)<<endl;
#define PIar(a,n) rep(i,n)cout<<a[i]<<" ";cout<<endl;
#define PIarr(a,n,m) rep(aa,n){rep(bb, m)cout<<a[aa][bb]<<" ";cout<<endl;}
const double EPS = 1e-9 ;
/*  ////////////////////////   C o d i n g  S p a c e   ////////////////////////  */
const int MAXN = 100 + 5 ;
int t1, t2, t3, n, cnt, K;
struct node {
	int x, y, z;
	bool operator <(const node& A) const {
		return x == A.x ? y < A.y : x < A.x;
	}
} s[MAXN], te;
bool G[MAXN][MAXN];
set<node> sen;
void input() {
	te.x = t1, te.y = t2, te.z = t3;
	if (te.x > te.y) swap(te.x, te.y);
	sen.insert(te);
	te.x = t1, te.y = t3, te.z = t2;
	if (te.x > te.y) swap(te.x, te.y);
	sen.insert(te);
	te.x = t2, te.y = t3, te.z = t1;
	if (te.x > te.y) swap(te.x, te.y);
	sen.insert(te);
}
void buildG() {
	rep(i, cnt) {
		rep(j, cnt) {
			if (s[i].x < s[j].x && s[i].y < s[j].y) {
				G[i][j] = 1;
			}
		}
	}
}
ll d[MAXN];
ll dp(int i) {
	ll& ans = d[i];
	if (ans >= 0) return ans;
      //刚开始时他的高就只有他自己的高
	ans = s[i].z;
	rep(j, cnt) {
		if (G[i][j]) {
                    //注意这里:是dp(j) + s[i].z 不是dp(j) + s[j].z
			ans = max(ans, dp(j) + s[i].z);
		}
	}
	return ans;
}
void Solve() {
	while (~SI(n), n) {
		cle(G, 0);
		sen.clear();
		rep(i, n) {
			SIII(t1, t2, t3);
			input();
		}
		cnt = 0;
		for (auto i = sen.begin(); i != sen.end(); i++, cnt++) {
			s[cnt].x = (*i).x, s[cnt].y = (*i).y, s[cnt].z = (*i).z;
		}
		buildG();
//		rep(i,cnt){
//			DGGG(s[i].x,s[i].y,s[i].z);
//		}
//		PIarr(G,10,10)
		ll ans = 0;
		rep(i, cnt) {
			cle(d, -1);
			ll te = dp(i);
			ans = max(te, ans);
		}
		printf("Case %d: maximum height = %lld\n", ++K, ans);
	}
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("C:\\Users\\Zmy\\Desktop\\in.txt", "r", stdin);
//	freopen("C:\\Users\\Zmy\\Desktop\\out.txt","w",stdout);
#endif
//iostream::sync_with_stdio(false);
//cin.tie(0), cout.tie(0);
//	int T;cin>>T;while(T--)
	Solve();
	return 0;
}
posted @ 2016-10-10 21:53  s1124yy  阅读(499)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3