Description
你有n个物品和m个包。物品有重量,且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?
Input
第一行两个整数n,m(1<=n<=24,1<=m<=100),表示物品和包的数量。
第二行有n个整数a[1],a[2],…,an,分别表示物品的重量。
第三行有m个整数c[1],c[2],…,cm,分别表示包的容量。
Output
如果能够装下,输出一个整数表示最少使用包的数目。若不能全部装下,则输出NIE。
Sample Input
4 3
4 2 10 3
11 18 9
Sample Output
2
HINT
Source
鸣谢Jcvb
代码里有注释.
跟Claris学到了新的状压DP压常数姿势(不压常就TLE QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define GET (ch>='0'&&ch<='9')
#define MAXN 16777216+2
#define lowbit(x) (x&(-x))
using namespace std;
int n,m,tmp;
int f[MAXN],g[MAXN],a[MAXN],c[101];//f_i 最少用几个包 g_i 最后一个包的剩余容量
bool cmp(int a,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]);
}