• noj [1480] 懒惰的风纪委Elaine (多重背包)


    http://ac.nbutoj.com/Problem/view.xhtml?id=1480

    • [1480] 懒惰的风纪委Elaine

    • 时间限制: 1000 ms 内存限制: 65535 K
    • 问题描述
    • Elaine是学园都市中的一个风纪委,每天都会接到命令对某个街道进行检查,并抓捕危险分子。她所在的风纪委支部附近有M条街道。这些街道由北到南并排均匀的分布在一条直线上,每条街道之间的距离都为1。但是众所周知,Elaine是一个很懒很懒的人(-..-说我坏话!!被我看到了!!),她不想一步一步走完所有街道,但好在她的好友Kuso为她制作了大量的传送卷轴。不过,因为Kuso的能力等级太低,他制作的卷轴有严重的缺点,他的卷则只能向南飞一段固定的距离(当然,他预先制作了很多种类的卷轴),而Elaine所在的风纪委支部却在最北边。每一次出去检查,Elain都要使用好几张卷轴。但如果是某些不能传送到的地方,Elaine只能走过去了。不过回来的话,她就可以用自带的传送系统传送到支部的传送点。

      有一天,Elaine想知道,如果她从风纪委支部出发,可以检查那些街道。她手里有N种传送卷轴(1,2,3,,,N),每个卷轴可以传送的距离为Ai,卷轴的数量为Ci。则Elaine靠那些卷轴,可以不走路而直接传送的有哪些街道?

    • 输入
    • 数据有多组输入。每一组数据的第一行有两个数:N,M(0<N<=100,0<M<=1000)。分别表示传送卷轴的种类数和街道数量。在第二行有2N个数,A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000)。数据输入以0 0结束。
    • 输出
    • 每组数据占一行,输出一个数,为Elaine可以传送到的街道总数。
    • 样例输入
    • 3 10
      1 2 4 2 1 1
      2 5
      1 4 2 1
      0 0
    • 样例输出
    • 8
      4
    • 先将多重背包转换成01背包,然后在求解01背包:
    • 任何一个正整数N  都可以分解成 N = 2^0 + 2^1 + 2^2+......+(剩下不足2^n的部分)
    • 例如:13  = 1 + 2 + 4 + 6
    • 这里是对数量进行拆分;  这样的好处可以很好的降低复杂度,从O(N*N)降到O(N*logN)
    •  1 #include<iostream>
       2 #include<cstring>
       3 #include<cstdio>
       4 #include<vector>
       5 using namespace std;
       6 
       7 int dp[1010];
       8 int a[110];
       9 vector<int> v;
      10 
      11 int main()
      12 {
      13     int n,m;
      14         while(scanf("%d%d",&n,&m)&&n&&m)
      15         {
      16 
      17             int i,j;
      18             for(i=0;i<n;i++)
      19             {
      20                 scanf("%d",&a[i]);
      21             }
      22             
      23             //多重背包转换成01背包
      24             v.clear();
      25             int t;
      26             for(i=0;i<n;i++)
      27             {
      28                 int nc;
      29                 scanf("%d",&nc);
      30                 t=1;
      31                 while(t<=nc)
      32                 {
      33                     v.push_back(t*a[i]);
      34                     nc-=t;
      35                     t=t*2;
      36                 }
      37                 if(nc>0){
      38                     v.push_back(nc*a[i]);
      39                 }
      40             }
      41             
      42             //01背包求解过程
      43             memset(dp,0,sizeof(dp));
      44             dp[0]=1;
      45             int sum=0;
      46             for(i=0;i<v.size();i++)
      47             {
      48                 for(j=sum==m?m-v[i]:sum;j>=0;j--)  //这个用到优化j=sum==m?m-v[i]:sum,这个优化是必要的,不然TLE
      49                 {
      50                     if(dp[j]!=0&&j+v[i]<=m){
      51                         dp[j+v[i]]=1;
      52                     }
      53                 }
      54                 sum+=v[i];
      55                 if(sum>m)
      56                 {
      57                     sum=m;
      58                 }
      59             }
      60             int cnt=0;
      61             for(i=1;i<=m;i++)
      62             {
      63                 if(dp[i])
      64                 {
      65                     cnt++;
      66                 }
      67             }
      68             printf("%d
      ",cnt);
      69         }
      70     return 0;
      71 }
  • 相关阅读:
    整数的二进制表示中1的个数
    最长公共子序列
    关于使浏览器崩溃的代码尝试
    wp7 独立存储
    动态引用样式表
    锋利的jQuery小记……
    DataGridVidw添加CheckBox。并通过一个 CheckBox来控制其全选。
    全选按钮的使用。winfrom程序中,对全选按钮的理解,欢迎拍砖!
    Ul li 超出文本显示省略号JS右键控制 本人QQ:267307031 空间更多技术咨询
    FileUpload控件
  • 原文地址:https://www.cnblogs.com/crazyapple/p/3202179.html
Copyright © 2020-2023  润新知