zoukankan      html  css  js  c++  java
  • 通过洛谷P2639看01背包

    题目描述
    
    Bessie像她的诸多姊妹一样,因为从Farmer John的草地吃了太多美味的草而长出了太多的赘肉。所以FJ将她置于一个及其严格的节食计划之中。她每天不能吃多过H (5 <= H <= 45,000)公斤的干草。 Bessie只能吃一整捆干草;当她开始吃一捆干草的之后就再也停不下来了。她有一个完整的N (1 <= N <= 500)捆可以给她当作晚餐的干草的清单。她自然想要尽量吃到更多的干草。很自然地,每捆干草只能被吃一次(即使在列表中相同的重量可能出现2次,但是这表示的是两捆干草,其中每捆干草最多只能被吃掉一次)。 给定一个列表表示每捆干草的重量S_i (1 <= S_i <= H), 求Bessie不超过节食的限制的前提下可以吃掉多少干草(注意一旦她开始吃一捆干草就会把那一捆干草全部吃完)。
    
    输入输出格式
    
    输入格式:
    * 第一行: 两个由空格隔开的整数: H 和 N * 第2到第N+1行: 第i+1行是一个单独的整数,表示第i捆干草的重量S_i。
    
    输出格式:
    * 第一行: 一个单独的整数表示Bessie在限制范围内最多可以吃多少公斤的干草。
    
    输入输出样例
    
    输入样例#1: 复制
    56 4
    15
    19
    20
    21
    输出样例#1: 复制
    56
    说明
    
    输入说明:
    
    有四捆草,重量分别是15, 19, 20和21。Bessie在56公斤的限制范围内想要吃多少就可以吃多少。
    
    输出说明:
    
    Bessie可以吃3捆干草(重量分别为15, 20, 21)。恰好达到她的56公斤的限制。

    看完题面,应当瞬间判断01背包(搜索超时了)想到记忆化~dp

    这个题相对01少了费用,变成了体积,于是就变成了区间最优体积(体积即费用的地位)

    下面是代码

     1 #include<iostream>      //头文件
     2 using namespace std;
     3 int n,m,a[10001],b[10001],f[100001]={0};     //要注意数据范围
     4 int main()
     5 {
     6     cin>>n>>m;
     7     for(int i=1;i<=m;i++)
     8     {
     9         cin>>a[i];        //输入每一捆干草的数量
    10     }
    11     for(int i=1;i<=m;i++)
    12     {
    13         for(int j=n;j>=a[i];j--)
    14         {
    15             if(f[j]<=f[j-a[i]]+a[i])f[j]=f[j-a[i]]+a[i];    //因为数据过大,所以要记得优化成一维的
    16         }
    17     }
    18     cout<<f[n]<<endl;            //输出结果
    19     return 0;
    20 }

    现在问题集中在11-17行

    即滚动数组优化和j的倒叙枚举

    用一个表格模拟下

    搜索代码的话

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<vector>
     6 #include<queue>
     7 #include<cstdlib>
     8 #include<fstream>
     9 #define maxn 868800
    10 using std::cin;using std::cout;using std::endl;using std::max;using std::min;
    11 int m,n,k,l,a,b,c,v[maxn],f[maxn];
    12 void dfs(int i,int j)
    13 {
    14     if(j>m)
    15     return ;
    16     f[j]=1;
    17     if(i==n+1)
    18     return ;
    19     dfs(i+1,j+v[i]);
    20     dfs(i+1,j);
    21 }
    22 int main()
    23 {
    24     cin>>m>>n;
    25     for(int i=1;i<=n;i++)
    26     cin>>v[i];
    27     dfs(1,0);
    28     for(int i=m;i>=1;i--)
    29     if(f[i]==1)
    30     {
    31     cout<<i<<endl;
    32     return 0; 
    33     }
    34     return 0;
    35 }

    0        
             
             
             
             

    从第一个开始选,从00开始推有

    f(i,j)=max(f(i-1,j-a[i]),f(i-1,j));

    f(i%2,j)=max(f(1^i%2,j-a[i]),f(1^i%2,j));

    这个没什么问题吧

    i是从1开始的,所以一开始给出的应该是f(1,m)=0;

    所以j是从m开始推出来的

    也就是说i,j是确定的状态;

    所以向下推;

    不会导致错误;

    我们再看看完全背包

    下篇吧

     

  • 相关阅读:
    专职DBA-MySQL体系结构与基本管理
    JSON
    MIME类型
    文件上传下载
    response常用的方法
    2020.11.27小记
    HTTP请求状态码
    1561. Maximum Number of Coins You Can Get
    1558. Minimum Numbers of Function Calls to Make Target Array
    1557. Minimum Number of Vertices to Reach All Nodes
  • 原文地址:https://www.cnblogs.com/iboom/p/8806884.html
Copyright © 2011-2022 走看看