zoukankan      html  css  js  c++  java
  • HihoCoder

    HihoCoder上有两道背包问题的problem,

    http://hihocoder.com/problemset/problem/1038 (01背包)

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    using namespace std;
    
    int main() 
    {
        //    Get input
        int n, m; cin >> n >> m;
        vector<int> need;
        vector<int> value;
    
        int tmp = n;
        while (tmp--)
        {
            int vneed, vvalue; 
            cin >> vneed >> vvalue;
            need.push_back(vneed);
            value.push_back(vvalue);
        }
    
        //    DP: dp[j] is max value by using up to j tickets
        vector<int> dp(m + 1, 0);
        for (int i = 0; i < n; i ++)
            for (int j = m; j > need[i]; j --) // note the dependency order
                dp[j] = std::max(dp[j], dp[j - need[i]] + value[i]);
        cout << dp[m] << endl;
    
        return 0;
    }

    http://hihocoder.com/problemset/problem/1043 (完全背包)

    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <unordered_map>
    using namespace std;
    
    int main() 
    {
        //    Get input
        int n, m; cin >> n >> m;
        vector<int> need;
        vector<int> value;
    
        int tmp = n;
        while (tmp--)
        {
            int vneed, vvalue; 
            cin >> vneed >> vvalue;
            need.push_back(vneed);
            value.push_back(vvalue);
        }
    
        //    DP: dp[j] is max value by using up to j tickets
        vector<int> dp(m + 1, 0);
        for (int i = 0; i < n; i ++)
            for (int j = 0; j <= m; j ++)
                if (j > need[i])
                    dp[j] = std::max(dp[j], dp[j - need[i]] + value[i]);
        cout << dp[m] << endl;
    
        return 0;
    }

    可以看到两者之间只有微妙的不同,目前搜到解释的最清楚的还是崔添翼的“背包九讲”(http://love-oriented.com/pack/P02.html)

    你会发现,这个伪代码与P01的伪代码只有v的循环次序不同而已。为什么这样一改就可行呢?首先想想为什么P01中要按照v=V..0的逆序来循环。这是因为要保证第i次循环中的状态f[i][v]是由状态f[i-1][v-c[i]]递推而来。换句话说,这正是为了保证每件物品只选一次,保证在考虑“选入第i件物品”这件策略时,依据的是一个绝无已经选入第i件物品的子结果f[i-1][v-c[i]]。而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加选一件第i种物品”这种策略时,却正需要一个可能已选入第i种物品的子结果f[i][v-c[i]],所以就可以并且必须采用v=0..V的顺序循环。这就是这个简单的程序为何成立的道理。

    简单直接,大师级别的理解和讲解

  • 相关阅读:
    也谈一下关于兔子的问题
    关于sql函数返回表
    关于1000瓶水的问题
    WWF的疑问
    天干和地支
    在若干个整数中找到相加之和为某个整数的所有组合的算法
    输出一个数组的全排列
    新的博客, 新的里程
    学习搜索引擎心得(10.2511.25)
    下一个阶段(用C++重写Lucene的计划)
  • 原文地址:https://www.cnblogs.com/tonix/p/4388974.html
Copyright © 2011-2022 走看看