Problem E ID:1005
简单题意:提供无限个若干种长为xi,宽为yi,高为zi的砖块,砖块可以调整方向(如长也可以为宽或高)。若一个砖块的长和宽分别比另一个砖块的长和宽小,则此砖块可以垒在后一个砖块的上面。问:最大可以垒多高?
解题思路形成过程:实际上是一种条件稍复杂些的最大递增子序列问题。
每种砖块的高共有三种情况(*3),其中每种情况分别对应两种长和宽(*2),所以每个砖块共有6种摆放方式,n个砖块有6*n种摆放方式。
每输入一种砖块类型,将对应的6种长、宽、高储存到相应的数组中。
按照砖块长的大小由小到大进行排序,如果两个砖块的长相同,则按照砖块宽的大小由小到大进行排序。
从第一个砖块开始按照求最大递增子序列问题的DP方式进行遍历,遍历至最后一个砖块,即可求得最大值。
感想:看似比最基本的最大递增子段和问题要复杂很多,但耐下心来就会发现,只是多了对数组进行存储和排序操作,DP的部分多一些思考罢了。重要的是要看出问题需要用什么方式来进行解决,如何抽象化。
代码:#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int n;
int x[181],y[181],z[181];
int dp[181];
void exch_1(int i)
{
x[i+1]=x[i];
y[i+1]=z[i];
z[i+1]=y[i];
}
void exch_2(int i)
{
x[i+2]=y[i];
y[i+2]=x[i];
z[i+2]=z[i];
x[i+3]=y[i];
y[i+3]=z[i];
z[i+3]=x[i];
}
void exch_3(int i)
{
x[i+4]=z[i];
y[i+4]=x[i];
z[i+4]=y[i];
x[i+5]=z[i];
y[i+5]=y[i];
z[i+5]=x[i];
}
void cmp()
{
for(int i=1;i<6*n;++i)
for(int j=0;j<i;++j)
{
if(x[j]>x[i])
{
int t=x[i];
x[i]=x[j];
x[j]=t;
t=y[i];
y[i]=y[j];
y[j]=t;
t=z[i];
z[i]=z[j];
z[j]=t;
}
else if(x[j]==x[i])
if(y[j]>y[i])
{
int t=y[i];
y[i]=y[j];
y[j]=t;
t=z[i];
z[i]=z[j];
z[j]=t;
}
}
}
int DP()
{
int cmax=z[0];
dp[0]=z[0];
for(int i=1;i<6*n;++i){
dp[i]=z[i];
for(int j=0;j<i;++j)
{
if(x[j]<x[i]&&y[j]<y[i])
if(dp[j]+z[i]>dp[i]){
dp[i]=dp[j]+z[i];
}
}
if(dp[i]>cmax)
cmax=dp[i];
}
return cmax;
}
int main()
{
freopen("1.txt","r",stdin);
int m=1;
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0;i<6*n;i+=6){
scanf("%d %d %d",&x[i],&y[i],&z[i]);
exch_1(i);
exch_2(i);
exch_3(i);
}
cmp();
int t=DP();
printf("Case %d: maximum height = %d\n",m++,t);
}
}
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int n;
int x[181],y[181],z[181];
int dp[181];
void exch_1(int i)
{
x[i+1]=x[i];
y[i+1]=z[i];
z[i+1]=y[i];
}
void exch_2(int i)
{
x[i+2]=y[i];
y[i+2]=x[i];
z[i+2]=z[i];
x[i+3]=y[i];
y[i+3]=z[i];
z[i+3]=x[i];
}
void exch_3(int i)
{
x[i+4]=z[i];
y[i+4]=x[i];
z[i+4]=y[i];
x[i+5]=z[i];
y[i+5]=y[i];
z[i+5]=x[i];
}
void cmp()
{
for(int i=1;i<6*n;++i)
for(int j=0;j<i;++j)
{
if(x[j]>x[i])
{
int t=x[i];
x[i]=x[j];
x[j]=t;
t=y[i];
y[i]=y[j];
y[j]=t;
t=z[i];
z[i]=z[j];
z[j]=t;
}
else if(x[j]==x[i])
if(y[j]>y[i])
{
int t=y[i];
y[i]=y[j];
y[j]=t;
t=z[i];
z[i]=z[j];
z[j]=t;
}
}
}
int DP()
{
int cmax=z[0];
dp[0]=z[0];
for(int i=1;i<6*n;++i){
dp[i]=z[i];
for(int j=0;j<i;++j)
{
if(x[j]<x[i]&&y[j]<y[i])
if(dp[j]+z[i]>dp[i]){
dp[i]=dp[j]+z[i];
}
}
if(dp[i]>cmax)
cmax=dp[i];
}
return cmax;
}
int main()
{
freopen("1.txt","r",stdin);
int m=1;
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=0;i<6*n;i+=6){
scanf("%d %d %d",&x[i],&y[i],&z[i]);
exch_1(i);
exch_2(i);
exch_3(i);
}
cmp();
int t=DP();
printf("Case %d: maximum height = %d\n",m++,t);
}
}