zoukankan      html  css  js  c++  java
  • 完全背包详解

    •  写在前面

    背包问题是动态规划里面很重要的一部分,彻底理解各种背包问题,对动态规划的后续学习有很大的帮助.

    更全的背包问题,可参看《背包九讲》

    学会了0-1背包后,多重背包、完全背包就比较容易理解.

     

    一.什么是“完全背包”?

    有这样一个问题:

      在你面前放着n种宝石,每种宝石重量为wi,价值为vi,数量无限;你有一个最多可以放m重量的背包。现在你想在不超重的情况下,是你带走的宝石价值最大,问最大价值是多少?

     

    二.如何做?

    我们来看一道题,链接.

    题目意思:你有一个空间为W的背包,在你前面放着n种石头,每种石头的价值为vi,体积为wi,数量无限.问:将背包装满,至少需要多少价值的石头?

    我们从第一种物品开始取,for(i=1 to n).

    设:dp[j]表示前i种物品,取得重量为j的石头时,需要的石头的最小价值.初始时dp[0]=0,其他为无穷大.

    那么:dp[j]=min(dp[j],dp[j-w[i]]+v[i]).

    即:

    for(int i=0; i<=m; ++i)
         dp[i]=INF;
    dp[0]=0;
    for(int i=0; i<n; ++i)
    {
         for(int j=w[i]; j<=m; ++j)
         {
               if(dp[j]>dp[j-w[i]]+v[i])
                     dp[j]=dp[j-w[i]]+v[i];
         }
    }

    注意:这儿的内循环是顺序!而0-1背包的内循环是逆序.

    为什么?

    我们在做0-1背包,计算dp[i][j]的时候,需要用到前面的值,而这个值是前i-1个物品的值(相当于更新前i-1个物品的值).

    而在做完全背包,计算dp[j]时,我们需要更新的是当前状态,也就是前i个物品的值.(也就是说:用前i-1个的值和当前值比较,更新当前值).

    代码:(跟着代码计算一遍即可理解)

    /*
    * this code is made by crazyacking
    * Verdict: Accepted
    * Submission Date: 2013-10-29-10.19
    * Time: 0MS
    * Memory: 137KB
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define max(a,b) (a>b?a:b)
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);

    const int MAXN=510;
    const int MAXM=10010;
    const int INF=(int)1e9+7;
    int dp[MAXM];
    int w[MAXN],v[MAXN];
    int main()
    {
         ios_base::sync_with_stdio(false);
         cin.tie(0);
         int t;
         cin>>t;
         while(t--)
         {
               int m,v1,v2;
               cin>>v1>>v2;
               m=v2-v1;
               int n;
               cin>>n;
               for(int i=0;i<n;++i)
               {
                     cin>>v[i]>>w[i];
               }
               for(int i=0;i<=m;++i)
                     dp[i]=INF;
               dp[0]=0;
               for(int i=0;i<n;++i)
               {
                     for(int j=w[i];j<=m;++j)
                     {
                           if(dp[j]>dp[j-w[i]]+v[i])
                                 dp[j]=dp[j-w[i]]+v[i];
                     }
               }
               if(dp[m]==INF)
                     cout<<"This is impossible."<<endl;
               else
                     cout<<"The minimum amount of money in the piggy-bank is "<<dp[m]<<"."<<endl;
         }
         return 0;
    }
    /*

    */

    转载请注明:http://www.cnblogs.com/crazyacking/p/3588624.html

  • 相关阅读:
    IDEA里运行程序时出现Error:scalac:error while loading JUnit4 , Scala signature JUnit4 has wrong version错误的解决办法(图文详解)
    全网最详细的最新稳定OSSEC搭建部署(ossec-server(CentOS6.X)和ossec-agent(CentOS6.X))(图文详解)
    SPSS学习系列之SPSS Modeler怎么修改默认的内存大小(图文详解)
    [转]innodb的锁时间
    [转]MySQL-死锁查询
    [转]mysql优化——show processlist命令详解
    mysql 手册
    [转]1、蓝牙核心技术了解(蓝牙协议、架构、硬件和软件笔记)
    [转]低功耗蓝牙技术连接的那点事
    [转]Ble蓝牙的使用手册
  • 原文地址:https://www.cnblogs.com/crazyacking/p/3588624.html
Copyright © 2011-2022 走看看