• UVA 437 The Tower of Babylon


    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
    ", kase, maxx);
    	}
    	return 0;
    }
    

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

  • 相关阅读:
    方法的重载
    this用法
    简单的随机数 代码和笔记
    java内存简单剖析
    day 28
    day 27
    day 26
    day 25
    day 24
    day 23
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10549479.html
Copyright © 2020-2023  润新知