如何在具有两个属性、每个属性的必要权重和最小总值的 3d 数组中实现背包算法?

Posted

技术标签:

【中文标题】如何在具有两个属性、每个属性的必要权重和最小总值的 3d 数组中实现背包算法?【英文标题】:How to implement knapsack algorithm in 3d array with two properties, necessary weights for each, and minimum total value? 【发布时间】:2019-03-31 18:18:04 【问题描述】:

卡车问题:

我们至少需要 W1 项目 1 的重量和 W2 项目 2 的重量,以获得最低总耗气值。 每辆卡车承载w1 重量的物品1,w2 重量的物品2 并消耗v 的汽油。

例如,输入将是:

5 60 5    // W1, W2, number of records below
3 36 120  // w1, w2, v
10 25 129 // w1, w2, v
5 50 250  // w1, w2, v
1 45 130  // w1, w2, v
4 20 119  // w1, w2, v

输出应该是:

249

我需要实现一个功能

int truck_knapsack(int W1, int W2, int w1[], int w2[], int v[], int n);

返回gas消耗的最小值,其中

n 是记录(卡车)的数量, v[] 耗气值, w1[] item1 的权重, w2[] item2 的权重, W1item1的必要重量, W2 item2 的必要重量。

我发现了类似的问题陈述和解决方案,但我无法为此找到解决方案。

我的老师指示我使用 3d 数组自下而上的方法来解决这个问题,但任何解决方案都会非常有帮助。

【问题讨论】:

发布你到目前为止所尝试的内容 你好,Sara,恐怕示例输入不清楚。第一行是什么(其注释与其他行的注释不同)?你还说输出应该是249,以便我验证我需要理解输入(这导致了我之前的问题)。请尝试解释输入示例,以便 SOers 可以更好地帮助您 @Ely 第一行输入是 item1 的总重量,item2 的总重量和后面输入的数量,之后的每个输入都有 item1 的重量,item2 的重量和 gas 的值花了。 【参考方案1】:

我相信您可以使用this answer 描述的策略。您的问题不是直接的背包公式,而是可以转换为一个。

设置 TotalW1 = ∑w1i - W1 和 TotalW2 = ∑w 2i - W2。现在你可以解决一个Mulitple Constraints Knapsack problem

最大化∑xivi 约束1:∑xjw1j ≤ TotalW1 - W1 约束2:∑xjw2j ≤ TotalW2 - W2

为了获得针对您的问题的最小化问题陈述的解决方案,您只需采用背包解决方案的补充,即未选择的卡车是在携带预期总重量最小的同时最小化气体消耗的卡车。 根据问题,输出应该是满足重量条件的卡车的总值。以下是显示您的问题示例的递归算法:

#include <stdio.h>

int max(int a, int b)

  return (a > b ? a : b);


int truck_knapsack(int W1, int W2, int w1[], int w2[], int v[], int n)

  if (n == 0 || W1 == 0 || W2 == 0)
    return 0;

  if (w1[n - 1] > W1 || w2[n - 1] > W2)
    return truck_knapsack(W1, W2, w1, w2, v, n - 1);

  return max(
      v[n - 1] + truck_knapsack(W1 - w1[n - 1], W2 - w2[n - 1], w1, w2, v, n - 1),
      truck_knapsack(W1, W2, w1, w2, v, n - 1));


int main()

  int W1 = 5;
  int W2 = 60;
  int w1[] = 3, 10, 5, 4, 1;
  int w2[] = 36, 25, 50, 45, 20;
  int v[] = 120, 129, 250, 130, 119;
  int n = 5;

  // the problem statement is a variation of Knapsack problem
  // turn it into a classical Knapsack problem

  // total1 = sum of w1 weights - W1
  int total1 = 0;
  for (int i = 0; i < n; i++)
    total1 += w1[i];
  total1 -= W1;

  // total2 = sum of w2 weights - W2
  int total2 = 0;
  for (int i = 0; i < n; i++)
    total2 += w2[i];
  total2 -= W2;

  // the result of the Knapsack algorithm is the max
  // bounded by total1 and total2
  // the result of the original problem statement is sum_of_values - result
  int result = truck_knapsack(total1, total2, w1, w2, v, n);
  int sum_values = 0;
  for (int i = 0; i < n; i++)
    sum_values += v[i];
  printf("%d\n", sum_values - result);

  return 0;

输出为 249。

【讨论】:

以上是关于如何在具有两个属性、每个属性的必要权重和最小总值的 3d 数组中实现背包算法?的主要内容,如果未能解决你的问题,请参考以下文章

如何在objective-c中比较两个具有很多属性的对象

如何在自定义 UITableViewCell 中更改 UIButton 标题的权重属性?

如何使用 LINQ 选择具有最小或最大属性值的对象

如何查看某个jquery对象所具有的的属性和方法

ArcGIS加权怎么确定权重

Sklearn SVM 系数属性 - 如何获取类名?