Pakowanie bzoj-3717 PA-2014
题目大意:给你n个物品m个包,物品有体积包有容量,问装下这些物品最少用几个包。
注释:$1le nle 24$,$1le mle 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 ",f[sum-1]); return 0; }
小结:好题,虽然卡常... ...