UVA 437 The Tower of Babylon (动态规划)

紫书上动态规划第二道例题。

这道题其实就是求DAG最长路,而且是无固定源点和终点的,基本上套用紫书上那种格式就行。

这道题难在如何表示。

这道题其实就是一个(len,wide,high)立方体可以拆成三个来看,所以直接造三种状态出来就好了,一个高为high,一个高为len,一个高为wide。

由于是要求下一个的长和宽必须严格小于当前的长和宽,我们先把这些都排序存起来,小的和小的比较,大的和大的比较可以剩下很多麻烦。

剩下的就是改一改DAG求最长路的代码,d【i】【j】表示第i个立方体的第j个状态可以造出的最大高度。

代码如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn = 35;

int n;
int d[maxn][5], G[maxn][5][5], a[5];
int length[maxn], wideth[maxn], high[maxn];

int dp(int x, int y) {
	int& ans = d[x][y];
	int l = G[x][y][0], w = G[x][y][1];
	if(ans)
		return ans;
	ans = G[x][y][2];
	for(int i = 1; i <= n; i++) {
		for(int j = 0; j < 3; j++) {
			int l2 = G[i][j][0], w2 = G[i][j][1];
			if(l > l2 && w > w2) {
				ans = max(G[x][y][2] + dp(i, j), ans);
			}
		}
	}
	return ans;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif
	int Case = 1;
	while(scanf("%d", &n) != EOF) {
		memset(d, 0, sizeof(d));
		if(n == 0)
			break;
		for(int i = 1; i <= n; i++) {
			scanf("%d%d%d", &a[0], &a[1], &a[2]);
			sort(a, a + 3);
			G[i][0][0] = a[0], G[i][0][1] = a[1], G[i][0][2] = a[2];
			G[i][1][0] = a[1], G[i][1][1] = a[2], G[i][1][2] = a[0];
			G[i][2][0] = a[0], G[i][2][1] = a[2], G[i][2][2] = a[1];
		}
		for(int i = 1; i <= n; i++) {
			for(int j = 0; j < 3; j++) {
				dp(i, j);
			}
		}
		int Max = 0;
		for(int i = 1; i <= n; i++) {
			for(int j = 0; j < 3; j++) {
				if(Max < d[i][j])
					Max = d[i][j];
			}
		}
		printf("Case %d: maximum height = %d\n", Case++, Max);
	}
	return 0;
}



你可能感兴趣的:(————动态规划————)