zoukankan      html  css  js  c++  java
  • 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

    正解:背包+状压$dp$。

    这道题只有$24$个物品,我们可以考虑状压。

    还有一个很显然的事,背包肯定是从大到小填的。

    那么我们就可以直接开始$dp$了,设$f[S]$表示当前物品集合为$S$,且当前背包所用容量为$f[S]$,$g[S]$为当前背包的编号,也就是背包数量。

    那么每次我们可以枚举一个物品加进来,如果没有炸掉当前背包,就可以直接填进去,否则就要开一个新背包,如果连新背包都开不下,那么这个转移就是不合法的。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define lb(x) (x & -x)
     6 #define inf (2147483640)
     7 #define SIZE (16777216)
     8 
     9 using namespace std;
    10 
    11 int f[SIZE],g[SIZE],bin[SIZE],a[110],c[110],n,m;
    12 
    13 il int gi(){
    14   RG int x=0,q=1; RG char ch=getchar();
    15   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    16   if (ch=='-') q=-1,ch=getchar();
    17   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    18   return q*x;
    19 }
    20 
    21 int main(){
    22 #ifndef ONLINE_JUDGE
    23   freopen("Pakowanie.in","r",stdin);
    24   freopen("Pakowanie.out","w",stdout);
    25 #endif
    26   n=gi(),m=gi();
    27   for (RG int i=0;i<n;++i) a[i]=gi(),bin[1<<i]=i;
    28   for (RG int i=1;i<=m;++i) c[i]=gi();
    29   sort(c+1,c+m+1),reverse(c+1,c+m+1),m=min(m,n+1);
    30   for (RG int S=1,all=1<<n;S<all;++S){
    31     f[S]=inf,g[S]=m+1;
    32     for (RG int i=S,s,x,res,tim;i;i^=s){
    33       s=lb(i),res=f[S^s],tim=g[S^s];
    34       if (res==inf) continue; x=bin[s];
    35       if (res+a[x]<=c[tim]) res+=a[x];
    36       else if (tim==m || c[tim+1]<a[x]) continue;
    37       else res=a[x],++tim;
    38       if (g[S]>tim) f[S]=res,g[S]=tim;
    39       else if (g[S]==tim && f[S]>res) f[S]=res;
    40     }
    41   }
    42   if (f[(1<<n)-1]==inf) puts("NIE");
    43   else cout<<g[(1<<n)-1]; return 0;
    44 }
  • 相关阅读:
    【引用】Android.mk简介
    android02android的四大组件
    rpm 安装指令全
    android04activity的布局管理器
    代码积累1统计图
    清除防火墙所有配置规则
    代码积累2tab页面滑动效果
    RHEL5 配置YUM源 安装RZSZ
    系统安全漏洞扫描软件
    liunx下防火墙的配置
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7668115.html
Copyright © 2011-2022 走看看