0/1背包问题

本文深入探讨了背包问题的动态规划解决方案,通过递归方式枚举所有可能的组合,找到最大价值的装填方案。文章提供了详细的代码实现,并解释了核心逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背包问题确实是一个让人有点费解的问题,它属于一种动态规划算法。以前确实也没有完全真正理解过这个算法,最近回头仔细品味,自觉有点心得领悟。将书本上的此算法根据自己的理解稍加整理,以一种更适合让人理解的方式呈现出来。

 

 

#include<stdio.h>
const int N=100;
int limitw;
int totv;
int maxv;
int option[N];
int cop[N];

struct Product 
{
    int weight;
    int value;
} a[N];

int n;
void find(int i, int tw) 
{
   int k;
   //1, i物品加入到当前的组合(条件是i物品的重量加上当前组合前面的所有物品的重量之和小于规定的总重量)
   if (tw+a[i].weight <= limitw) {
       cop[i] = 1;//标记第i个物品加入到当前的组合
       if (i < n-1) {
           find(i+1, tw+a[i].weight);//加上i的重量
       } else {//否则的话i=n-1,一个完整的组合完毕
           int sum = 0;
           for (k = 0;k < n;k++) {
               if(cop[k]) {
                   sum += a[k].value;
               }
           }

           if (sum > maxv) {//如果当前组合的总值大于之前组合的总值则更新maxv
               for (k = 0;k < n;k++) {
                   option[k] = cop[k];
               }
               maxv = sum;
           }
       }
       cop[i] = 0;//find返回了表示i加入到当前组合的case已经递归完毕,现在退回到当前的函数栈来了。所以恢复i的标记,为下面的i不加入当前组合的case做准备
   }

   //0,i物品不加入到当前的组合是不需要任何条件。这里我让每个物品都走了不加入当前组合的case是为了便于理解,但是牺牲了些效率(因为有些情况如果i物品不加入的话则当前组合的可能总值一定会比已经存在的maxv要小,所以这种组合其实没必要走下去)
  if(i < n-1) {
       find(i+1, tw);
   } else {
       int sum = 0;
       for (k = 0;k < n;k++) {
           if(cop[k]) {
               sum += a[k].value;
           }
       }

       if (sum > maxv) {
           for (k = 0;k < n;k++) {
               option[k] = cop[k];
           }
           maxv = sum;
       }
   }

}

int main(int argc, _TCHAR* argv[])
{
    int k,w,v;
    printf("物品总数: ");
    scanf("%d",&n);

    for(k=0;k < n;k++)
    {
        printf(" 第%d种物品(重量,价值) : ", k+1);
        scanf("%d, %d", &w, &v);
        a[k].weight = w;
        a[k].value = v;
    }

    printf(" 背包所能承受的总总量: ");
    scanf("%d",&limitw);
    
    maxv = 0;
    for(k=0;k < n;k++) {
        cop[k] = 0;
    }

    find(0, 0);


    printf(" 最佳装填方案是: \n");
    for(k=0;k < n;k++) {
        if(option[k]) printf(" 第%d种物品\n", k+1);
    }
    printf(" 总价值=%d\n", maxv);
}

 

执行结果如下:

对于当前的组合,每一个物品都有两种分支,选择加入当前组合或者不加入当前组合。那么一共有n个物品的话,则可以有2的n次方个不同组合。所以我们的程序通过递归的方式覆盖了这个2的n次方个组合,然后将这2的n次方个组合的maxv进行比较得到其中最大的那个值。思路就是这么简单。

在这2的n次方个组合中,由于对组合物品的重量有限制,所以每次在选在第i个物品加入当前组合时就需要做一个是否超重的判断。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值