bzoj3717 [PA2014]Pakowanie

Description

你有n个物品和m个包。物品有重量,且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?

Input

第一行两个整数n,m(1<=n<=24,1<=m<=100),表示物品和包的数量。
第二行有n个整数a[1],a[2],…,a[n](1<=a[i]<=10^8),分别表示物品的重量。
第三行有m个整数c[1],c[2],…,c[m](1<=c[i]<=10^8),分别表示包的容量。

Output

如果能够装下,输出一个整数表示最少使用包的数目。若不能全部装下,则输出NIE。

Sample Input

4 3
4 2 10 3
11 18 9

Sample Output

2

首先我们有贪心的思想就是背包肯定是从大往小选。

再接着由于物品数$n<=24$,我们可以拿来状压。

设$f[S]$表示当前物品集合为$S$,且当前背包所用容量为$f[S]$,$g[S]$为当前背包的编号,也就是背包数量。

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int f[(1<<24)-1],id[(1<<24)-1],g[(1<<24)-1];
 7 int a[25],c[101],n,m,inf=2e9;
 8 bool cmp(int a,int b)
 9 {
10   return a>b;
11 }
12 int lowbit(int x)
13 {
14   return x&(-x);
15 }
16 int main()
17 {int i,j;
18   cin>>n>>m;
19   for (i=1;i<=n;i++)
20     {
21       scanf("%d",&a[i]);
22       id[(1<<i-1)]=i;
23     }
24   for (i=1;i<=m;i++)
25     {
26       scanf("%d",&c[i]);
27     }
28   sort(c+1,c+m+1,cmp);
29   for (i=1;i<(1<<n);i++)
30     {
31       g[i]=m+1;
32       f[i]=inf;
33       for (j=i;j;j-=lowbit(j))
34     {
35       int S=i-lowbit(j);
36       int tim=g[S],res=f[S];
37       if (res==inf) continue;
38       if (res+a[id[lowbit(j)]]<=c[tim]) res+=a[id[lowbit(j)]];
39       else if (tim==m||c[tim+1]<a[id[lowbit(j)]]) continue;
40       else {res=a[id[lowbit(j)]];tim++;}
41       if (tim<g[i]) f[i]=res,g[i]=tim;
42       else if (g[i]==tim&&f[i]>res) f[i]=res; 
43     }
44     }
45   if (f[(1<<n)-1]==inf) cout<<"NIE";
46   else 
47   cout<<g[(1<<n)-1];
48 }

 

 

 

那么每次我们可以枚举一个物品加进来,如果没有炸掉当前背包,就可以直接填进去,否则就要开一个新背包,如果连新背包都开不下,那么这个转移就是不合法的
posted @ 2017-10-16 21:35  Z-Y-Y-S  阅读(221)  评论(0编辑  收藏  举报