码迷,mamicode.com
首页 > 其他好文 > 详细

HihoCoder - 01\完全背包

时间:2015-04-03 06:48:47      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

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的顺序循环。这就是这个简单的程序为何成立的道理。

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

HihoCoder - 01\完全背包

标签:

原文地址:http://www.cnblogs.com/tonix/p/4388974.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!