了解c中的背包解决方案

时间:2017-08-27 08:39:36

标签: c

#include <stdio.h>
#include <conio.h>

void main() {
    int p[20], w[20], kn[20][20], x[20], i, j, n, weight;
    Clrscr();
    printf("\nEnter the value of n ");
    scanf("%d", &n);
    printf("\nEnter the price of the items ");
    for (i = 0; i < n; i++) {
        scanf("%d", &p[i]);
    }
    printf("\nEnter the weight of the items ");
    for (i = 0; i < n; i++) {
        scanf("%d", &w[i]);
    }
    printf("\nEnter the weight of the knapsack ");
    scanf("%d", &weight);
    printf("\nThe knapsack is ");
    for (i = 0; i <= n; i++) {
        printf("\n");
        for (j = 0; j <= weight; j++) {
            if (i == 0 || j == 0) {
                kn[i][j] = 0;
            } else
            if (w[i - 1] > j) {
                kn[i][j] = kn[i - 1][j];
            } else {
                kn[i][j] = (kn[i - 1][j] > (kn[i - 1][j - w[i - 1]] + p[i - 1])) ?
                            kn[i - 1][j] : (kn[i - 1][j - w[i - 1]] + p[i - 1]);
            }
            printf("%d ", kn[i][j]);
        }
    }
    printf("\n\nThe optimal solution is %d", kn[n][weight]);
    i = n;
    j = weight;
    while (i != 0) {
        if (kn[i][j] == kn[i - 1][j]) {
            x[i-1] = 0;
            i = i - 1;
        } else {
            x[i - 1] = 1;
            j = j - w[i - 1];
            i = i - 1;
        }
    }
    printf("\n\nThe 0/1 knapsack is ");
    for (i = 0; i < n; i++) {
        printf("\nX[%d]=%d", i + 1, x[i]);
    }
    getch();
}

嘿伙计们......我是'C'的新手,但我从教科书中尝试了这个背包问题。我真的不明白它是如何工作的,特别是不理解这一行 kn[i][j]=(kn[i-1][j]>(kn[i-1][j-w[i-1]]+p[i-1]))?kn[i-1][j]:(kn[i-1][j-w[i-1]]+p[i-1]);

好吧,如果有人想解释请做...
非常感谢你:))

3 个答案:

答案 0 :(得分:5)

这是由两个状态权重和索引定义的背包的动态编程实现。我们上面的sol以自下而上的方式构建,这意味着我们从最初的一个项目开始,并考虑到成本最大成本和重量的约束来构建我们的n个项目的解决方案。对于上述问题,我定义了索引,j定义了权重。

因此kn [i] [j]定义了问题设定者通过从0到第i个索引的项目可以做出的最大利润,其中麻袋的容量为权重j。

找到可以从n个项目获得的最大值的方法是以下条件的最大值

  • 通过n-1 (此处为i-1)项目和权重W 获得的最大值(此处在每次迭代j中)
  • 包括第n项的值+由n-1项获得的最大值和包含第n项重量的重量W.

我在评论中包含了每个stmt的原因。

因此,对于每个项目,我们可以将其包含在溶胶中,或者我们不能。

for(i=0;i<=n;i++)
    {
        printf("\n");
        for(j=0;j<=weight;j++)
        {
            if(i==0||j==0)     //if no of items to be included is 0 or max capacity is 0 the sol is 0
            {
                kn[i][j]=0;
            }
            else if(w[i-1]>j)   //if the nth item is greater than the weight j we can remove the item from our solution. 
            {  
                kn[i][j]=kn[i-1][j];
            }
            else
            {  //writing this cond in easier format
                kn[i][j]=max( val[i-1] + k[i-1][j-w[i-1]] , k[i-1][j])
            }
            printf("%d ",kn[i][j]);
        }
}

每个人都有困难在第二和第二第三个条件因此,为了人类,我们举一个例子i = 1。因此,背包只有1个项目,由索引i = 0表示。

如果此第0项的重量大于最大重量(从0到重量w逐步递增),我们不能包含此项目。因此,对于所有j,我们将背包的最大值设为kn [1] [j] = kn [i-1] [j],即kn [0] [j],其反过来为0,因为i = 0直到我们达到一个阶段其中w [i-1] == j。

在更简单的英语中,这意味着背包可以容纳1个项目但是重量约束小于项目i-1的最大值(这里是数组中的第0个项目,但实际上是第1个项目)是0,直到j增加到权重&gt; =以i = 1表示的此项(即数组中的第0项)。

其他(一旦j代表的重量是&gt;项目i-1重量)

(现在我们有2个条件,因为虽然这个项目的重量小于W或其他j

1.如果我们包括此项目以前包含的项目的总重量和此当前项目(我们正在建立溶胶自下而上)可能超过总重量,因此我们不想包括该项目)背包值k [i] [ j] = k [i-1] [j]仅包含之前的项目。

  1. 我们可以包括这个当前项目因此K [i] [j] =这个第i项的值+由i-1项获得的最大值(这里i = 1没有),其具有当前项目的权重j-权重.kn [i] [j] = max(val [i-1] + k [i-1] [jw [i-1]],k [i-1] [j])
  2. 因此i = 1我们有一个背包值作为val [当前项目] + 0(因为没有以前的项目。)

    迭代继续自下而上构建解决方案。

    希望这有帮助!

答案 1 :(得分:1)

答案在于您是否采用i项目。

如果您使用i项,则问题会缩小,以找到包含i-1项且背包重量为j-w[i]的最佳解决方案。

如果您不接受i - 项目只是跳过它。所以解决方案是kn[i-1][j]。 为什么j?因为您没有采取任何物品,所以您可以使用相同的重量来填充背包。

现在你有两个选择,你可以选择一个最大限度填充的选项。这就是为什么你需要找到这两个中的最大值的原因。

你使用三元运算符做了什么。

或者,您可以使用max()函数来获取两者中的最大值。这也会得到相同的答案。

你也可以使用ol&#39;简单if-else

if( kn[i-1][j]>(kn[i-1][j-w[i-1]]+p[i-1]))
  kn[i][j]=kn[i-1][j];
else
  kn[i][j]=(kn[i-1][j-w[i-1]]+p[i-1]);

这个三元运算符最终归结为if-else

j基本上是我们正在考虑的权重。我们正试图解决较小权重的问题。 j表示。帮助我们解决子问题是有帮助的。

答案 2 :(得分:1)

这是三元运营商。

如果在三个操作数上使用任何运算符,则变量称为三元运算符。它可以表示? :。 它也称为条件运算符

三元运营商的优势:

  

使用?:减少行代码的数量并提高性能   申请。

语法:

expression-1 ? expression-2 : expression-3

在上面的符号表达式-1中,条件和表达式-2和表达式-3将是值或变量或语句或任何数学表达式。如果condition为true,则表达式-2将被执行,否则将执行表达式-3。

例如:

a<b ? printf("a is less") : printf("a is greater");