jzoj4743-积木【状压dp】

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/88364143

正题


题目大意

有长方体积木 n n 块,求能搭成的最高高度。


解题思路

考虑状态压缩,设 f s , i , j f_{s,i,j} 表示积木使用状态为 s s ,最下面的是第 i i 块,状态为 j j

状态:对于一个长方体 a , b , c a,b,c

  1. a b a*b 的底
  2. a c a*c 的底
  3. b c b*c 的底

首先枚举状态,然后枚举当前放哪个,然后枚举上次放哪个,然后枚举最上面哪个的放置状态,然后暴力动态转移。

时间复杂度 O ( 2 n n 2 ) O(2^n*n^2)


c o d e code

#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*c
	for(int i=1;i<=n;i++)
	  for(int k=0;k<3;k++)
	    ans=max(ans,f[MS-1][i][k]);
	printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/88364143