如何知道2个背包问题中带走了哪些物品?

时间:2018-11-24 13:50:01

标签: c# algorithm knapsack-problem

此功能需要:

  1. car1_laod :KnapSack1大小。
  2. car2_load :KnapSack2大小。
  3. N :商店中的商品数量。
  4. 装载:一个承载物品重量的数组。
  5. 价格:一个包含商品价格的数组。
  6. car1_items :该列表包含我在car1中挑选并放入的物品。
  7. car2_items :该列表包含我在car2中挑选并放入的物品。

目标是了解通过向car1和car2添加商品可以获得的最大利润 项目不能选择两次。

    public static int GetMaximumProfit(int car1_load, int car2_load, int N, 
     int[] loads, int[] prices, List<int> car1_items, List<int> car2_items)
    {
        Console.WriteLine();
        int[,] dp = new int[car1_load+1, car2_load+1];
        for(int i=0;i<N;i++)
        {
            for (int ks1=car1_load;ks1>=0;ks1--)
            {
                for(int ks2 = car2_load;ks2>=0;ks2--)
                {
                    if (ks1 >= loads[i] && ks2 >= loads[i])
                    {
                        dp[ks1, ks2] = max(
                                       dp[ks1, ks2],
                                       dp[ks1 - loads[i], ks2] + prices[i],
                                       dp[ks1, ks2 - loads[i]] + prices[i]
                                        );
                    }
                    else if (ks1 >= loads[i])
                    {  
                        dp[ks1, ks2] = Math.Max(
                                       dp[ks1, ks2],
                                       dp[ks1 - loads[i], ks2] + prices[i]
                                        );
                    }
                    else if (ks2 >= loads[i])
                    {

                        dp[ks1, ks2] = Math.Max(
                                       dp[ks1, ks2],
                                       dp[ks1, ks2 - loads[i]] + prices[i]
                                        );
                    }

                }
            }



        }



        cout(dp);
        Console.WriteLine("Answer : " + dp[car1_load, car2_load]);

        return dp[car1_load,car2_load];
    }

示例:

输入:

N = 4,car1_load = 5,car2_load = 2

负载[4] = {1,2,3,5}

价格[4] = {20,10,15,25}

输出:

要插入列表中的项目是选择要在两辆车中装载的产品的索引[基于1]

利润= 45

Car1项= [2,3]

Car2物品= [1]

我的输出:

Example output of the function

我计算了最大利润。

问题是我不知道如何在dp阵列上回溯才能知道这些物品的来源。

1 个答案:

答案 0 :(得分:1)

您应该在商品索引的数组中添加另一个维度,类似于the dynamic programming solution to the regular knapsack problem(您也许可以在没有该维度的情况下进行计算,但至少会更复杂)。

我将具体内容留给您,但这将为您提供类似的信息:

dp[i, ks1, ks2] = max(
    dp[i-1, ks1, ks2],
    dp[i-1, ks1 - loads[i], ks2] + prices[i],
    dp[i-1, ks1, ks2 - loads[i]] + prices[i]
);

现在,您需要从头开始,并反复找出以上哪个值是最大值,然后继续该值。

只需检查左侧是否等于右侧的任何值即可。

int ks1 = car1_load, ks2 = car2_load;
for (i = N; i > 0; i--)
{
    if (ks1 >= loads[i] && dp[i, ks1, ks2] == dp[i-1, ks1 - loads[i], ks2] + prices[i])
    {
        // Add i to car 1
        ks1 -= loads[i];
    }
    else if (ks2 >= loads[i] && dp[i, ks1, ks2] == dp[i-1, ks1, ks2 - loads[i]] + prices[i])
    {
        // Add i to car 2
        ks2 -= loads[i];
    }
    // if it's equal to dp[i-1, ks1, ks2], we don't need to do anything
}

根据您实际更改代码以将项目索引添加为数组维的方式,代码看起来可能与此有所不同。