Perhaps you have heard of the legend of the Tower of Babylon. Nowadays many details of this tale have been forgotten. So now, in line with the educational nature of this contest, we will tell you the whole story: The babylonians had n types of blocks, and an unlimited supply of blocks of each type. Each type-i block was a rectangular solid with linear dimensions tex2html_wrap_inline32 . A block could be reoriented so that any two of its three dimensions determined the dimensions of the base and the other dimension was the height. They wanted to construct the tallest tower possible by stacking blocks. The problem was that, in building a tower, one block could only be placed on top of another block as long as the two base dimensions of the upper block were both strictly smaller than the corresponding base dimensions of the lower block. This meant, for example, that blocks oriented to have equal-sized bases couldn’t be stacked. Your job is to write a program that determines the height of the tallest tower the babylonians can build with a given set of blocks.
【题目分析】
表示状态的方式十分巧妙,每一个物体最多有3种不同类型的面,只需要用序号+0/1/2表示就可以了。
关于递推和记忆化搜索:
记忆化搜索显然是可以的。
然而我思考了递推,发现层数不好确定,这样复杂度会变成n^3,显然比记忆化搜索的n^2要差许多。但是对于这样一道n<=30的题目来说。显然怎么搞都可以吧。
【代码】 借鉴隔壁sdfzyhx
#include <cstdio>
#include <cstring>
int dp[31][3],ans,num[31][3],kase=0,n;
inline void match(int x,int & y,int & z)
{
if (!x) y=1,z=2;
else if (x==1) y=0,z=2;
else y=0,z=1;
}
inline int max(int a,int b)
{return a>b?a:b;}
int solve(int k,int p)
{
if (dp[k][p]) return dp[k][p];
int i,j,x1,y1,x2,y2,z;
match(p,x1,y1);
for (i=1;i<=n;i++)
for (j=0;j<3;j++)
{
match(j,x2,y2);
if ((num[k][x1]<num[i][x2]&&num[k][y1]<num[i][y2])||(num[k][x1]<num[i][y2]&&num[k][y1]<num[i][x2]))
dp[k][p]=max(dp[k][p],solve(i,j));
}
dp[k][p]+=num[k][p];
return dp[k][p];
}
int main()
{
while (scanf("%d",&n),n)
{
memset(dp,0,sizeof dp);
for (int i=1;i<=n;++i) scanf("%d%d%d",&num[i][0],&num[i][1],&num[i][2]);
ans=0;
for (int i=1;i<=n;++i)
for (int j=0;j<3;++j)
ans=max(ans,solve(i,j));
printf("Case %d: maximum height = %d\n",++kase,ans);
}
}
【关于递推写法】
个人想到的是写一个while,每次n^2转移一下。然后判断一下是否有更新,如果没有,就跳出来就可以了。