【BZOJ3717】[PA2014]Pakowanie 状压DP
2017-11-05 16:54
435 查看
【BZOJ3717】[PA2014]Pakowanie
Description
你有n个物品和m个包。物品有重量,且不可被分割;包也有各自的容量。要把所有物品装入包中,至少需要几个包?Input
第一行两个整数n,m(1<=n<=24,1<=m<=100),表示物品和包的数量。第二行有n个整数a[1],a[2],…,a
(1<=a[i]<=10^8),分别表示物品的重量。
第三行有m个整数c[1],c[2],…,c[m](1<=c[i]<=10^8),分别表示包的容量。
Output
如果能够装下,输出一个整数表示最少使用包的数目。若不能全部装下,则输出NIE。Sample Input
4 34 2 10 3
11 18 9
Sample Output
2题解:一开始想到了栅栏那题,以为是爆搜+剪枝,结果狂TLE不止,后来发现是状压。。。
显然我们应该贪心的从容量较大的包开始选,然后用f[S]表示已经用过的物品状态为S时,最少用几个包,g[S]表示在用的包最少的前提下,最后一个包的最大剩余容量。
转移时用到了一些卡常小技巧~
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,m,N; int f[1<<24],g[1<<24],w[1<<24],c[110]; int main() { scanf("%d%d",&n,&m),N=(1<<n)-1; int i,j,k,S; for(i=0;i<n;i++) scanf("%d",&w[i]); for(i=n-1;i>=0;i--) w[1<<i]=w[i]; for(i=1;i<=m;i++) scanf("%d",&c[i]); sort(c+1,c+m+1); f[0]=m+1,g[0]=0; for(i=1;i<=N;i++) { for(j=i;j;j-=k) { k=j&-j,S=i^k; if(g[S]>=w[k]&&(f[S]>f[i]||(f[S]==f[i]&&g[S]>g[i]+w[k]))) f[i]=f[S],g[i]=g[S]-w[k]; else if(c[f[S]-1]>=w[k]&&(f[S]>f[i]+1||(f[S]==f[i]+1&&c[f[i]]>g[i]+w[k]))) f[i]=f[S]-1,g[i]=c[f[i]]-w[k]; } } if(!f ) printf("NIE"); else printf("%d",m+1-f ); return 0; }
相关文章推荐
- 【bzoj3717】[PA2014]Pakowanie 状压dp
- BZOJ 3717: [PA2014]Pakowanie 状压dp
- [bzoj3717][PA2014]Pakowanie_动态规划_状压dp
- [BZOJ3717]-[PA2014]Pakowanie-状压DP
- bzoj 3717: [PA2014]Pakowanie
- bzoj3717 [PA2014]Pakowanie(状压DP)
- 【PA2014】【BZOJ3717】Pakowanie
- BZOJ3717 [PA2014]Pakowanie
- bzoj3717 [PA2014]Pakowanie
- [bzoj3711][PA2014]Druzyny【分治】【dp】
- bzoj 3711: [PA2014]Druzyny 分治+线段树优化dp
- 【BZOJ】【P3721】【PA2014 Final】【Bazarek】【题解】【DP】
- bzoj3446 [Usaco2014 Feb]Cow Decathlon 状压DP
- BZOJ 3727 PA2014 树DP 解题报告
- 【XSY1285】【BZOJ3814】【清华集训2014】简单回路 状压DP
- BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )
- 【BZOJ4042】【CERC2014】parades 状压DP
- BZOJ 3727 PA2014 Final Zadanie 树形DP
- BZOJ 3727 PA2014 Final Zadanie 树形DP
- 【BZOJ3727】PA2014 Final Zadanie 树形DP