zoukankan      html  css  js  c++  java
  • 【BZOJ3717】[PA2014]Pakowanie 状压DP

    【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

    题解:一开始想到了栅栏那题,以为是爆搜+剪枝,结果狂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[N])	printf("NIE");
    	else	printf("%d",m+1-f[N]);
    	return 0;
    }

     

  • 相关阅读:
    表单元素
    Form表单、四种常见的POST请求提交数据方式、MIME
    html table
    jsop
    如何成为一名优秀的前端工程师
    CSS代码检查工具推荐:CSS Lint
    前端CSS规范整理
    使用渐进式 JPEG 来提升用户体验
    移动前端系列——移动页面性能优化(转)
    HTML5页面资源预加载(Link prefetch)功能加速页面加载速度
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7787818.html
Copyright © 2011-2022 走看看