大意:给你一些三维的坐标的箱子,箱子的三维在给定的值内可以任意变换,一个箱子可以无限次使用,求一种方法使得叠箱子的高度最大。
思路:首先看题目的限定条件,即确定长、宽的二维坐标不可能相等,相等则结果是无穷大,这一题的难点主要是在于建图,一开始我是通过排序来建图的,结果算出来了,但感觉比较麻烦,于是去网上看到有一个更加巧妙的方法,他是没有排序而直接建图的。
建好图后,就是简单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;
}