[bzoj3717][PA2014]Pakowanie_动态规划_状压dp

Pakowanie bzoj-3717 PA-2014

题目大意:给你n个物品m个包,物品有体积包有容量,问装下这些物品最少用几个包。

注释:$1\le n\le 24$,$1\le m\le 100$


想法:以为是什么超级牛逼的背包dp,结果就是状压dp

状态:f[s]表示装s状态的物品需要多少背包,g[s]表示在f[s]的前提下,最大的背包剩余的容量。

转移:直接判断最后一个能不能装下当前物品,转移即可。

还有就是这个题卡常,只能直接用Lowbit枚举1,不能全枚举,会T... ...

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 17000000 
#define lowbit(x)   (x&(-x))
using namespace std;
int n,m,tmp;
int f[N],g[N],a[N],c[101];
bool cmp(const int &a,const int &b){return a>b;}
int main()
{
	scanf("%d%d",&n,&m); int sum=(1<<n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++) scanf("%d",&c[i]); sort(c+1,c+m+1,cmp);
	for(int i=n;i;i--) a[(1<<(i-1))]=a[i];
	for(int i=1;i<sum;i++)
	{
		f[i]=m+1;g[i]=-1;
		for(int j=i;j;j-=tmp)
		{
			tmp=lowbit(j);int x=i-tmp;
			if(a[tmp]<=g[x]&&(f[x]<f[i]||(f[x]==f[i]&&g[x]-a[tmp]>g[i])))
				f[i]=f[x],g[i]=g[x]-a[tmp];
			else if((f[x]+1<f[i]||(f[x]+1==f[i]&&c[f[x]+1]>g[i]+a[tmp]))&&c[f[x]+1]>=a[tmp])
				f[i]=f[x]+1,g[i]=c[f[i]]-a[tmp];
		}
	}
	if(f[sum-1]>m) puts("NIE");
	else printf("%d\n",f[sum-1]);
	return 0;
}

小结:好题,虽然卡常... ...

猜你喜欢

转载自www.cnblogs.com/ShuraK/p/9375027.html
今日推荐