题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1069
一开始看到这题我想不到什么思路,后来翻《算法竞赛入门经典》时发现它是第九章第二节的例题9-2巴比伦塔
书上提供了两点解题的点:
1.用有向无环图DAG的模型,其模板代码为:
int dp(int i)
{
int& ans = d[i];
if (ans > 0)return ans;
ans = 1;
for (int j = 1; j <= n; j++)
if (G[i][j])ans = max(ans, dp(j) + 1);
return true;
}
其中d[i]表示从点I到终点的最大值,G[i][j]表示i是否能到j点
2.如果用G[i][j]数组解题,会容易出现数组过大的情况,所以设置了(idx,k)这个二元组来表示,idx为立方体的编号,1<=k<=3,表示三条边。
最后的代码为:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
#include <cmath>
#include <string>
#include <queue>
#include <stack>
using namespace std;
const int N = 35;
int maps[N][N];
int d[N][N];
int k;
int n;
void get(int *v, int i, int height)
{
int ii=0;
int j;
for (j = 1; j <= 3; j++)
if (j != height)
v[ii++] = maps[i][j];
}
int dp(int i, int j)
{
int ii, jj;
int& ans = d[i][j];
if (ans > 0)
{
return ans;
}
ans = 0;
int v[3], v2[3];
get(v, i, j);
for(ii=1;ii<=n;ii++)
for (jj = 1; jj <= 3; jj++)
{
get(v2, ii, jj);
if (v2[0] < v[0] && v2[1] < v[1])
ans = max(ans, dp(ii, jj));
}
ans += maps[i][j];
return ans;
}
int main()
{
int i, j, k;
int ans;
k = 1;
while (scanf("%d",&n)!=EOF)
{
if (n == 0)
break;
memset(d, 0, sizeof(d));
ans = 0;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= 3; j++)
scanf("%d", &maps[i][j]);
sort(maps[i] + 1, maps[i] + 1 + 3);
}
for(i=1;i<=n;i++)
for (j = 1; j <= 3; j++)
{
ans = max(dp(i, j), ans);
}
printf("Case %d: maximum height = %d\n", k++, ans);
}
return 0;
}