现在的位置: 首页 > 综合 > 正文

UVA 437 The Tower of Babylon

2019年04月09日 ⁄ 综合 ⁄ 共 2539字 ⁄ 字号 评论关闭

大意:给你一些三维的坐标的箱子,箱子的三维在给定的值内可以任意变换,一个箱子可以无限次使用,求一种方法使得叠箱子的高度最大。

思路:首先看题目的限定条件,即确定长、宽的二维坐标不可能相等,相等则结果是无穷大,这一题的难点主要是在于建图,一开始我是通过排序来建图的,结果算出来了,但感觉比较麻烦,于是去网上看到有一个更加巧妙的方法,他是没有排序而直接建图的。

建好图后,就是简单DAG上的最长路径了,记忆化搜索解之,d[i]表示以i为起点的最长路径的长度。

如果这题推广到多维的话,那么无论是排序还是其他的方法似乎都不太好建图,那样的话,只有加上每个箱子只能使用一次这个限制条件似乎才方便建图。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
using namespace std;

const int MAXN = 1010;

struct Edge
{
	int x, y, z;
}A[MAXN];

int d[MAXN];
int G[MAXN][MAXN];
bool vis[MAXN];

int n;
int times;

void init()
{
	memset(G, 0, sizeof(G));
	memset(vis, 0, sizeof(vis));
}

int check(int i, int j)
{
	if((A[i].x > A[j].x && A[i].y > A[j].y) || (A[i].x > A[j].y && A[i].y > A[j].x)) return 1;
		return 0;
}

void build()
{
	for(int i = 0; i < 3*n; i++)
	{
		for(int j = 0; j < 3*n; j++)
		{
			if(check(i, j))
			{
				G[i][j] = 1;
			}
		}
	}
}

int dp(int i)
{
	int& ans = d[i];
	if(vis[i]) return ans;
	vis[i] = 1;
	ans = A[i].z;
	for(int j = 0; j < 3*n; j++) if(G[i][j])
		ans = max(ans, dp(j)+A[i].z);
	return ans;
}

int read_case()
{
	init();
	scanf("%d", &n);
	if(!n) return 0;
	for(int i = 0; i < n; i++)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		A[3*i].x = x, A[3*i].y = y, A[3*i].z = z;
		A[3*i+1].x = x, A[3*i+1].y = z, A[3*i+1].z = y;
		A[3*i+2].x = y, A[3*i+2].y = z, A[3*i+2].z = x;
	}
	return 1;
}

void solve()
{
	build();
	int ans = 0;
	for(int i = 0; i < 3*n; i++) ans = max(ans, dp(i));
	printf("Case %d: ", ++times);
	printf("maximum height = %d\n", ans);
}

int main()
{
	times = 0;
	while(read_case())
	{
		solve();
	}
	return 0;
}

 列出全排列:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
using namespace std;

const int MAXN = 1010;

struct Edge
{
	int x, y, z;
}A[MAXN];

int d[MAXN];
int G[MAXN][MAXN];
bool vis[MAXN];

int n;
int times;
int tot;

void init()
{
	tot = 0;
	memset(G, 0, sizeof(G));
	memset(vis, 0, sizeof(vis));
}

int check(int i, int j)
{
	if((A[i].x > A[j].x && A[i].y > A[j].y) || (A[i].x > A[j].y && A[i].y > A[j].x)) return 1;
		return 0;
}

void build()
{
	for(int i = 0; i < tot; i++)
	{
		for(int j = 0; j < tot; j++)
		{
			if(check(i, j))
			{
				G[i][j] = 1;
			}
		}
	}
}

int dp(int i)
{
	int& ans = d[i];
	if(vis[i]) return ans;
	vis[i] = 1;
	ans = A[i].z;
	for(int j = 0; j < tot; j++) if(G[i][j])
		ans = max(ans, dp(j)+A[i].z);
	return ans;
}

int read_case()
{
	init();
	scanf("%d", &n);
	if(!n) return 0;
	for(int i = 0; i < n; i++)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		A[tot].x = x, A[tot].y = y, A[tot++].z = z; //1
		A[tot].x = x, A[tot].y = z, A[tot++].z = y;
		A[tot].x = y, A[tot].y = x, A[tot++].z = z; //2
		A[tot].x = y, A[tot].y = z, A[tot++].z = x; //3
		A[tot].x = z, A[tot].y = x, A[tot++].z = y;
		A[tot].x = z, A[tot].y = y, A[tot++].z = x;	
	}
	return 1;
}

void solve()
{
	build();
	int ans = 0;
	for(int i = 0; i < tot; i++) ans = max(ans, dp(i));
	printf("Case %d: ", ++times);
	printf("maximum height = %d\n", ans);
}

int main()
{
	times = 0;
	while(read_case())
	{
		solve();
	}
	return 0;
}

抱歉!评论已关闭.