1. 程式人生 > >BZOJ3717 PA2014Pakowanie(狀壓dp)

BZOJ3717 PA2014Pakowanie(狀壓dp)

17. read 子集 efi == algo online 一個 情況下

  顯然貪心地有盡量先往容量大的背包裏放。設f[i]為i子集物品最小占用背包數,g[i]為該情況下最後一個背包的剩余容量,轉移顯然。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>
9) {if (c==-) f=-1;c=getchar();} while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 24 #define M 102 int n,m,a[N],b[M],f[1<<N],g[1<<N],lg2[1<<N]; int main() { #ifndef ONLINE_JUDGE freopen("bzoj3717.in","r",stdin); freopen(
"bzoj3717.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(); for (int i=0;i<n;i++) a[i]=read(); for (int i=1;i<=m;i++) b[i]=read(); sort(b+1,b+m+1);reverse(b+1,b+m+1); for (int i=0;i<n;i++) lg2[1<<i]=i; memset(f,
42,sizeof(f)); f[0]=0;int s=(1<<n)-1; for (int i=0;i<(1<<n);i++) if (f[i]<=m) for (int j=s^i,t=j&-j;j;j^=t,t=j&-j) if (g[i]>=a[lg2[t]]) { if (f[i]<f[i|t]) f[i|t]=f[i],g[i|t]=g[i]-a[lg2[t]]; else if (f[i]==f[i|t]) g[i|t]=max(g[i|t],g[i]-a[lg2[t]]); } else if (b[f[i]+1]>=a[lg2[t]]) { if (f[i]+1<f[i|t]) f[i|t]=f[i]+1,g[i|t]=b[f[i|t]]-a[lg2[t]]; else if (f[i]+1==f[i|t]) g[i|t]=max(g[i|t],b[f[i|t]]-a[lg2[t]]); } if (f[(1<<n)-1]>m) cout<<"NIE"; else cout<<f[(1<<n)-1]; return 0; }

BZOJ3717 PA2014Pakowanie(狀壓dp)