zoukankan      html  css  js  c++  java
  • #状压dp,背包,贪心#洛谷 5997 [PA2014]Pakowanie

    题目

    你有 (n) 个物品和 (m) 个包。物品有重量,且不可被分割;

    包也有各自的容量。要把所有物品装入包中,至少需要几个包?


    分析

    考虑物品的数量很小,首先优先选容量大的背包,
    (f[S])表示当前选择的物品二进制状态所需要的背包数量,
    但这不够,还要维护当前最后一个背包能够最大剩余的容量(g[S])
    那当前就是考虑新开一个背包或者是填入最后一个背包
    时间复杂度(O(2^nn)),但是时限5s,可以通过


    代码

    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=25,M=1<<24;
    int two[N],a[N],n,m,b[N],dp[M],cho[M+1],f[M];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    signed main(){
    	n=iut(),m=iut(),two[0]=1;
    	for (rr int i=0;i<n;++i) two[i+1]=two[i]<<1;
    	for (rr int i=0;i<n;++i) cho[two[i]]=i;
    	for (rr int i=0;i<n;++i) a[i]=iut();
    	for (rr int i=1;i<=m;++i) b[i]=iut();
    	sort(a,a+n),reverse(a,a+n),
    	sort(b+1,b+1+m),reverse(b+1,b+1+m),
    	memset(dp,42,sizeof(dp)),dp[0]=0;
    	for (rr int S=1;S<two[n];++S){
    		for (rr int j=S;j;j&=j-1){
    			rr int i=cho[-j&j],now=S^two[i];
    			if (f[now]>=a[i]&&(dp[now]<dp[S]||(dp[now]==dp[S]&&f[S]<f[now]-a[i])))
    			    dp[S]=dp[now],f[S]=f[now]-a[i];
    			if (dp[now]<m&&b[dp[now]+1]>=a[i]&&(dp[now]+1<dp[S]||(dp[now]+1==dp[S]&&f[S]<b[dp[now]+1]-a[i])))
    			    dp[S]=dp[now]+1,f[S]=b[dp[now]+1]-a[i];
    		}
    	}
    	if (dp[two[n]-1]>m) printf("NIE");
    	    else printf("%d",dp[two[n]-1]);
    	return 0;
    }
    
  • 相关阅读:
    父亲对子女的话
    开通博客
    在linux下安装MySQLdb及基本操作
    java 词汇表速查手册
    java数据源的几种配置
    DBCP的参数配置
    Linux crontab定时执行任务
    很好看的Button CSS.
    C# 创建活动目录.txt
    解密存储过程
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13924212.html
Copyright © 2011-2022 走看看