各种背包问题的思路和C语言实现

背包问题:

  1. 0-1背包问题:给定n种物品和一个容量为V的背包,每种物品都有自己的重量w[i]和价值v[i],在限定的总重量内,选择其中若干件物品装入背包,使得背包中的物品总价值最大。

  2. 多重背包问题:相比起第一种,每种物品都有独立的数量可供选择使用

  3. 完全背包问题:相比起第一种,每种物品都可以无限重复选择

第一种:

#include <stdio.h>
#define max(a, b) ((a) > (b) ? (a) : (b))

//搞出最大值的函数

int main() {
    int n, V;
   scanf("物品数量:%d 背包容量%d", &n, &V);
    
    int w[n], v[n];
    int i,j;
    for (i = 0; i < n; i++) {
        scanf("%d %d", &w[i], &v[i]);
    }
    
    int dp[n+1][V+1];
    for (i = 0; i <= n; i++) {
        for (j = 0; j <= V; j++) {
            dp[i][j] = 0;

// 初始化动态规划数组
        }
    }
    
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= V; j++) {
            if (w[i-1] <= j) {

// 当前物品重量小于等于背包容量,选择放入或不放入该物品,选择总价值更大的方案
                dp[i][j] = max(dp[i-1][j-w[i-1]] + v[i-1], dp[i-1][j]);
            } else {

// 当前物品重量大于背包容量,无法放入该物品,继承上一个状态的价值
                dp[i][j] = dp[i-1][j];
            }
        }
    }
    
    printf("%d\n", dp[n][V]);
    
    return 0;
}

随便提一嘴,博主的dev-c++版本似乎有些老,博主在最初几版代码老是报错,原因如下:

在 C99 标准之前,C 语言不允许在 for 循环中声明变量,而在 C99 标准及以后,C 语言支持在 for 循环中声明变量。博主就属于前者,

for (int i = 0; i < n; i++) 

这种就会去报错,大家可以避免

第二种:

看起来和第一种差不多,实际上确实差不多,多了要用指针了,麻烦一些

使用了 malloc 函数来动态地分配了多个数组的内存空间,这些数组用于解决多重背包问题:

int *w = (int *)malloc(sizeof(int) * n);//存储每个物品的重量
int *v = (int *)malloc(sizeof(int) * n);//存储每个物品的价值
int *num = (int *)malloc(sizeof(int) * n); // 记录每种物品的数量
int *dp = (int *)malloc(sizeof(int) * (V + 1));
其中,w 数组存储每个物品的重量,v 数组存储每个物品的价值,num 数组记录每个物品的数量,dp 数组则用于存储求解过程中的结果,使用malloc原因是它可以动态分配内存,每次的数量价值重量都不一样,所以要动态的分配合理内存。

代码如下:

#include <stdio.h>
#include <stdlib.h>

//为了使用malloc函数

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))

int main() {
    int n, V;
    printf("请输入物品数量和背包容量:");
    scanf("%d %d", &n, &V);
    
    // 输入每种物品的重量、价值和数量
    int *w = (int *)malloc(sizeof(int) * n);
    int *v = (int *)malloc(sizeof(int) * n);
    int *num = (int *)malloc(sizeof(int) * n);

// 记录每种物品的数量
    int i,j,k;
    for (i = 0; i < n; i++) {
        scanf("%d %d %d", &w[i], &v[i], &num[i]);
    }
    
  
    int *dp = (int *)malloc(sizeof(int) * (V + 1));
    for (i = 0; i <= V; i++) {
        dp[i] = 0; 
    }
    
    // 遍历每种物品
    for (i = 0; i < n; i++) {
        // 对于每种物品,从背包容量到该物品重量来逆序遍历
        for (j = V; j >= w[i]; j--) {
            // 计算当前物品的最大可选数量
            int maxNum = min(num[i], j / w[i]); 
            // 遍历当前物品的可选数量,更新动态规划数组
            for (k = 1; k <= maxNum; k++) {
                dp[j] = max(dp[j], dp[j - k * w[i]] + k * v[i]);
            }
        }
    }
    
    // 输出最大总价值
    printf("最大总价值为:%d\n", dp[V]);
    
    // 释放内存
    free(dp);
    free(w);
    free(v);
    free(num);
    
    return 0;
}

第三种:

跟第二种差不多,思路一样

#include <stdio.h>
#include <stdlib.h>

#define max(a, b) ((a) > (b) ? (a) : (b))

int main() {
    int n, V,i,j;
    printf("请输入物品数量和背包容量:");
    scanf("%d %d", &n, &V);
    
    // 输入每种物品的重量和价值
    int *w = (int *)malloc(sizeof(int) * n);
    int *v = (int *)malloc(sizeof(int) * n);
    
    for (i = 0; i < n; i++) {
        scanf("%d %d", &w[i], &v[i]);
    }
    
  
    int *dp = (int *)malloc(sizeof(int) * (V + 1));
    for ( i = 0; i <= V; i++) {
        dp[i] = 0; 
    }
    
    // 遍历每种物品
    for ( i = 0; i < n; i++) {
        // 对于每种物品,从该物品重量开始遍历
        for ( j = w[i]; j <= V; j++) {
            dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
        }
    }
    
    // 输出最大总价值
    printf("最大总价值为:%d\n", dp[V]);
    
    // 释放内存
    free(v);
    free(w);
    free(dp);
    
    return 0;
}
 

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值