zoukankan      html  css  js  c++  java
  • 洛谷 1776 宝物筛选 【多重背包+二进制拆分】

    【题解】

      显然是个多重背包。但直接写背包会超时。所以我们试着优化。

      怎么优化?我们发现,每个物品的个数$ai$可以拆分成几个数的和,用这些数中的某几个之和可以表示出$1$到$ai$的所有整数,并且不会超过$ai$

      这样我们可以把ai个相同的物品拆分成若干个互相独立的物品,然后跑01背包。

      那么如何对$ai$进行拆分?拆分出来的数就是相加起来不超过$ai$的2的$i$次幂以及$ai$减去2的$i$次幂之和的结果。

      例如我们可以把19拆分成$1,2,4,8,3$

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int n,w,f[200010];
     5 inline int read(){
     6     int f=1,k=0; char c=getchar();
     7     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
     8     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
     9     return k*f;
    10 }
    11 int main(){
    12     n=read(); w=read();
    13     while(n--){
    14         int vi=read(),wi=read(),ai=read(),i;
    15         for(i=0;((1<<(i+1))-1)<=ai;i++){
    16             for(int j=w;j>=(wi<<i);j--)
    17             f[j]=max(f[j-(wi<<i)]+(vi<<i),f[j]);
    18         }
    19         int tmp=ai-(1<<i)+1;
    20         vi=vi*tmp; wi=wi*tmp;
    21         for(int j=w;j>=wi;j--) f[j]=max(f[j-wi]+vi,f[j]);
    22     }
    23     printf("%d
    ",f[w]);
    24     return 0;
    25 }
    View Code
  • 相关阅读:
    java监听者模式
    使用tc编写流量控制脚本
    Android apk集成
    就这样
    嘴不笨来试试??太好玩儿了,看看谁厉害?
    老板的三句话
    电脑设置wifi
    JDBC
    使用git的一般操作
    模板引擎Velocity学习系列
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8331030.html
Copyright © 2011-2022 走看看