正题
题目大意
有长方体积木nnn块,求能搭成的最高高度。
解题思路
考虑状态压缩,设fs,i,jf_{s,i,j}fs,i,j表示积木使用状态为sss,最下面的是第iii块,状态为jjj:
状态:对于一个长方体a,b,ca,b,ca,b,c
- a∗ba*ba∗b的底
- a∗ca*ca∗c的底
- b∗cb*cb∗c的底
首先枚举状态,然后枚举当前放哪个,然后枚举上次放哪个,然后枚举最上面哪个的放置状态,然后暴力动态转移。
时间复杂度O(2n∗n2)O(2^n*n^2)O(2n∗n2)
codecodecode
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=17;
struct node{int a,b,c;
}c[N];
int f[1<<N][N][3],MS,n,ans;
bool check(int x,int y,int l,int w)
{return x>=l&&y>=w||x>=w&&y>=l;}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d%d%d",&c[i].a,&c[i].b,&c[i].c);MS=(1<<n);for(int s=0;s<MS;s++){for(int i=1;i<=n;i++){if(s&(1<<(i-1))) continue;int mb=s|(1<<(i-1));for(int j=1;j<=n;j++)for(int k=0;k<3;k++){int l,w;if(k==0) l=c[j].a,w=c[j].b;else if(k==1) l=c[j].a,w=c[j].c;else l=c[j].b,w=c[j].c;if(check(c[i].a,c[i].b,l,w))f[mb][i][0]=max(f[mb][i][0],f[s][j][k]+c[i].c);if(check(c[i].a,c[i].c,l,w))f[mb][i][1]=max(f[mb][i][1],f[s][j][k]+c[i].b);if(check(c[i].b,c[i].c,l,w))f[mb][i][2]=max(f[mb][i][2],f[s][j][k]+c[i].a);}}}//1-a*b 2-a*c 3-b*cfor(int i=1;i<=n;i++)for(int k=0;k<3;k++)ans=max(ans,f[MS-1][i][k]);printf("%d",ans);
}