蛮力法 解决0/1背包问题

实验项目1 蛮力法

实验题目 使用蛮力法解决0/1背包问题。

问题描述:给定n个重量(weight)为{w1, w2, … ,wn}价值(key)为{v1, v2, … ,vn}的物品和一个容量为C(contain)的背包,求这些物品中的一个最有价值的子集,且要能够装到背包中。
eg:示例:
背包容量C=15kg
物品1:重量2kg,价值2$
物品2:重量12kg,价值4$
物品3:重量1kg,价值2$
物品4:重量1kg,价值1$
物品5:重量4kg,价值10$

img

实验目的

  1. 理解算法的时间复杂度;
  2. 熟练设计和生成问题的解空间:设计一种穷举策略将物品装入背包的各种装法都找出来,并能够在计算机中存储和表示。
  3. 理解蛮力法的局限性;
  4. 实验要求
  5. 掌握用递归或循环生成n个元素的全部子集的算法设计方法;

按上图示例数据求解出问题的一个最优解:装入哪几个物品价值最大,总重量和总价值各是多少?

蛮力法的主要框架

// 辅助数组,防止递归死循环
int visited[5] = { 0 };
// w容量,key价值,len:weight数组长度 depth 深度
void backpack(int w, int* weight, int* key, int len, int depth, int tempSum) {
    // 如果到达物品数组的末尾 地柜出口
    if (depth == len) {
        return;
    }
    // 不选择当前物品
    visited[depth] = 0;
    backpack(w, weight, key, len, depth + 1, tempSum);
    // 如果能选择当前物品(背包容量足够)
    visited[depth] = 1; // 选择当前物品
    backpack(w - arr[depth], weight, key, len, depth + 1, tempSum + key[depth]); // 递归调用
}

不难看出使用的是递归的方式

算法代码

#include<stdio.h>

// 辅助数组,防止递归死循环
int visited[5] = { 0 };
// 寻找最大值
int sumMax = 0;
//
int weightSum = 0;
// 寻找最大值对应装填方式
int method[5] = { 0 };
int capacity = 15; // 背包容量
int count = 0;
//判断容量是否合理
int LessCapacity(int len,const int* arr){
    int sumWeight = 0;
    for (int i = 0; i < len; ++i) {
        if(visited[i] == 1)
        sumWeight += arr[i];
    }
//    满足小于等于15 为 1
    return sumWeight<=capacity ? 1:0;
}
// 遍历当前状态,更新最大价值和装填方式
void Traverse(int* arr,  int len, int tempSum, int depth) {
    printf("--------------------------------------------\n");
    int weight = 0;
    // 打印当前状态
    printf("重量: ");
    for (int i = 0; i < len; ++i) {
        printf("%d  ", arr[i]);
    }
    printf("\n");
    printf("选择: ");
    for (int i = 0; i < len; i++) {
        printf("%d  ", visited[i]);
        if(visited[i]){
            weight+=arr[i];
        }
    }
    printf("\n");
    printf("当前总重量: %d\n", weight);
    printf("当前总价值: %d\n", tempSum);
    if(weight>capacity){
        printf("该情况不符合要求!\n");
    }else{
        printf("该情况符合要求!\n");
    }
    printf("--------------------------------------------\n\n");
    // 如果当前价值大于已知的最大价值,则更新最大价值和method数组
    if (tempSum > sumMax && LessCapacity(len,arr)) {
        sumMax = tempSum;
//        更新选择方法
        for (int i = 0; i < len; i++) {
            method[i] = visited[i];
        }
    }

}

// 背包问题的递归函数
void backpack(int w, int* arr, int* key, int len, int depth, int tempSum) {
    // 如果到达物品数组的末尾或背包容量已满,则遍历当前状态
    if (depth == len) {
        count++;
        Traverse(arr, len, tempSum, depth);
        return;
    }
    // 不选择当前物品
    visited[depth] = 0;
    backpack(w, arr, key, len, depth + 1, tempSum);

    // 如果能选择当前物品(背包容量足够)
    visited[depth] = 1; // 选择当前物品
    backpack(w - arr[depth], arr, key, len, depth + 1, tempSum + key[depth]); // 递归调用
}
// 判断重量<=15

int main() {
    // 重量
    int weight[] = { 2, 12, 1, 1, 4 };
    // 重量对应的价值
    int key[] = { 2, 4, 2, 1, 10 };

    backpack(capacity, weight, key, 5, 0, 0); // 调用背包问题的递归函数

    printf("----------------------------------分隔符----------------------------------\n");
    printf("总共有%d种情况\n",count);
    printf("重量: ");
    for (int i = 0; i < sizeof(weight)/sizeof (int); ++i) {
        printf("%d  ", weight[i]);
    }
    printf("\n");
    printf("选择: ");
    for (int i = 0; i < sizeof(weight)/sizeof (int); i++) {
        printf("%d  ", method[i]);
        if(method[i] == 1){
            weightSum+=weight[i];
        }
    }
    printf("\n 最终重量:%d",weightSum);
    printf("\n 最终最优金额:%d",sumMax);
    return 0;
}
posted @   Yang0710  阅读(100)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
世间美好与你环环相扣 - 柏松
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 尹初七

作曲 : 柏松

编曲 : 彭圣杰

偏偏秉烛夜游

偏偏秉烛夜游

午夜星辰 似奔走之友

爱你每个结痂伤口

酿成的陈年烈酒

入喉尚算可口

入喉尚算可口

怎么泪水 还偶尔失守

邀你细看心中缺口

裂缝中留存 温柔

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

让樱花偷偷 吻你额头

让世间美好 与你环环相扣

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

此时已莺飞草长 爱的人正在路上

此时已莺飞草长 爱的人正在路上

我知他风雨兼程 途经日暮不赏

穿越人海 只为与你相拥

此刻已皓月当空 爱的人手捧星光

我知他乘风破浪 去了黑暗一趟

感同身受 给你救赎热望

知道你不能 还要你感受

知道你不能 还要你感受

让星光加了一点彩虹

当樱花开的纷纷扬扬

当世间美好 与你环环相扣

特别鸣谢:槿葵,我们的海报制作妹妹。

原唱:柏松

吉他:柏松

和声:柏松

录音:柏松

混音:张强

点击右上角即可分享
微信分享提示