【问题标题】:Modified dynamic knapsack - problematic input?修改后的动态背包 - 输入有问题?
【发布时间】:2014-10-22 20:29:14
【问题描述】:

以下是this SPOJ 问题的尝试解决方案。输入是:

  1. 一定数量的硬币的总重量
  2. 使用货币的硬币的价值和相应的重量,目标是找到给定金额的最小可能货币价值。

我从背包问题的wikipedia article 中稍微修改了背包问题的动态规划解决方案——我只是先按重量对硬币进行排序,这样我就不必遍历所有硬币来获得最小值和(希望)确保总重量等于容量。 (请看代码,真的很简单,有注释。)

但是,根据法官的说法,有一个输入我的算法给出了错误的答案。你能建议算法有什么问题吗?

#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>

using namespace std;

typedef unsigned int weight_t;
typedef unsigned int value_t;

struct coin {
    weight_t weight;
    value_t value;
};

coin make_coin(weight_t weight, value_t value) {
    coin ret;
    ret.weight = weight;
    ret.value = value;
    return ret;
}

bool compare_by_weight(const coin& coin1, const coin& coin2) {
    return coin1.weight < coin2.weight;
}

int main() {
    unsigned int test_cases;
    cin >> test_cases;
    while(test_cases--) {
        //Initialization
        unsigned int number_of_coins, n = 0;
        weight_t empty_pig, full_pig, coin_weight, coins_weight;
        value_t coin_value, min_value, current_value = 0;
        vector<coin> coins;
        vector<unsigned int> min_value_for_the_weight;

        //Input
        cin >> empty_pig >> full_pig;
        cin >> number_of_coins;
        n = number_of_coins;
        while(n--) {
            cin >> coin_value >> coin_weight;
            coins.push_back(make_coin(coin_weight, coin_value));
        }

        //Input processing
        coins_weight = full_pig - empty_pig;
        sort(coins.begin(), coins.end(), compare_by_weight);
        min_value_for_the_weight.resize(coins_weight+1);
        for(unsigned int i = 0; i < coins_weight; i++) min_value_for_the_weight[i] = 0;

        //For all weights
        for(unsigned int i = 1; i <= coins_weight; i++) {
            //Find the smallest value
            min_value = numeric_limits<value_t>::max();
            for(unsigned int j = 0; j < number_of_coins; j++) {
                //The examined coin weights more or same than examined total weight and we either already have put a coin
                //in, or this is the first one
                if(coins[j].weight <= i && (min_value_for_the_weight[i - coins[j].weight] > 0 || i == coins[j].weight)){
                    current_value = coins[j].value + min_value_for_the_weight[i - coins[j].weight];
                    if(current_value < min_value) min_value = current_value;
                } else break;  // <- this I deleted to get accepted
            }
            if(min_value == numeric_limits<value_t>::max()) min_value = 0;
            min_value_for_the_weight[i] = min_value;
        }

        //If the piggy empty, output zero
        if(!min_value_for_the_weight[coins_weight] && coins_weight != 0)
            cout << "This is impossible." << endl;
        else
            cout << "The minimum amount of money in the piggy-bank is " << min_value_for_the_weight[coins_weight] << "." << endl;
        }
    return 0;
}

【问题讨论】:

    标签: c++ algorithm dynamic-programming knapsack-problem


    【解决方案1】:

    empty_pig == full_pig 的情况有问题,因为您忽略了重复逻辑特殊情况,即min_value_for_the_weight 的第零个条目。

    另一个错误是,如果coins[j].weight &gt; i,则break 只是一个好主意。旧代码可以breakcoin[j].weight &lt;= i 和另一半合取为假,即不可能制造重量为i - coins[j].weight 的硬币。这发生在以下测试用例中。

    1
    10 13
    2
    2 2
    3 3
    

    我们必须使用重量为 2 或 3 的硬币来制造重量 3。重量 1 被正确确定为不可能。权重 2 被正确确定为可能。对于重量 3,我们尝试重量 2 硬币,确定重量 1 是不可能的,break 在尝试重量 3 硬币之前。结果是代码错误地报告了不可能将权重设为 3。

    【讨论】:

    • 谢谢!因此,对于空猪,我输出最小重量 0。但是,逻辑仍然存在问题。 (我编辑了帖子,希望没问题。)
    • 如果我删除了逻辑中的else break,它就会被接受。你能解释一下为什么会产生错误的结果吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    相关资源
    最近更新 更多