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

一.问题引入

 给定n个重量为(w1,w2,…,wn)、价值为{V1,V2,…,Vn)的物品和一个容l量是为C的背包,0/1背包问题(0/1 knapsack problcm)是求这些物品中的一个最有价值的子集,并且要能够装到背包中。

二.算法实例

用蛮力法解决0/1背包问题,需要考虑给定n个物品集合的所有子集,找出所有总重量不超过背包容量的子集,计算每个可能子集的总价值,然后找到价值最大的子集。例如,给定4个物品的重量为(7,3,4,5),价值为{42,12,40,25),和一个容量为10的背包,下表给出了蛮力法求解0/1背包问题的过程。 

三.蛮力法过程

蛮力法求解的过程
序号子集总重量(weight)总价值(value)
1空集00
2{1}742
3{2}312
4{3}440
5{4}525
6{1,2}1054
7{1,3}1182
8{1,4}1267
9{2,3}752
10{2,4}837
11{3,4}965
12{1,2,3}1494
13{1,2,4}1579
14{1,3,4}16107
15{2,3,4}1294
16{1,2,3,4}19119

 四.算法实现(C++) 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

int main()
{
    int num, maxv = 0;
    int n, c, * w, * v, tempw, tempv;
    int i, j, k;

    printf("input the number and the volume:");
    scanf("%d%d", &n, &c);

    w = new int[n];
    v = new int[n];

    printf("input the weights:");
    for (i = 0; i < n; i++)
        scanf("%d", &w[i]);

    printf("input the values:");
    for (i = 0; i < n; i++)
        scanf("%d", &v[i]);

    printf("Selected items:\n");

    for (num = 0; num < pow(2, n); num++) //每一个num对应一个解
    {
        k = num;
        tempw = tempv = 0;
        printf("Solution %d: ", num);

        for (i = 0; i < n; i++) //n位二进制
        {
            if (k % 2 == 1)
            { //如果相应的位等于1,则代表物体放进去,如果是0,就不用放了
                tempw += w[i];
                tempv += v[i];
                printf("%d ", i);
            }
            k = k / 2; //二进制转换的规则
        }

        printf("Total weight: %d,Total value: %d\n", tempw,tempv);

        //循环结束后,一个解空间生成,
        //判断是否超过了背包的容积,
        //如果没有超,判断当前解是否比最优解更好
        if (tempw <= c)
        {
            if (tempv > maxv)
                maxv = tempv;
        }
    }

    printf("The maxvalue is %d.\n", maxv);

    delete[] w;
    delete[] v;

    return 0;
}

结果实现: 

五.算法实现(Python) 

import math

n = int(input("input the number: "))
c = int(input("input the volume: "))

w = []
v = []

print("input the weights:")
for i in range(n):
    w.append(int(input()))

print("input the values:")
for i in range(n):
    v.append(int(input()))

maxv = 0

print("Selected items:")

for num in range(int(math.pow(2, n))):
    k = num
    tempw = tempv = 0
    print(f"Solution {num}: ", end='')

    for i in range(n):
        if k % 2 == 1:
            tempw += w[i]
            tempv += v[i]
            print(f"{i} ", end='')
        k //= 2

    print(f"(Total weight: {tempw},Total value: {tempv})")

    if tempw <= c and tempv > maxv:
        maxv = tempv

print(f"The maxvalue is {maxv}.")

结果实现:

六.算法实现(java) 

package suanfa;

import java.util.Scanner;

public class suanfa {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("input the number: ");
        int n = scanner.nextInt();

        System.out.print("input the volume: ");
        int c = scanner.nextInt();

        int[] w = new int[n];
        int[] v = new int[n];

        System.out.println("input the weights:");
        for (int i = 0; i < n; i++) {
            w[i] = scanner.nextInt();
        }

        System.out.println("input the values:");
        for (int i = 0; i < n; i++) {
            v[i] = scanner.nextInt();
        }

        int maxv = 0;

        System.out.println("Selected items:");
        for (int num = 0; num < Math.pow(2, n); num++) {
            int k = num;
            int tempw = 0;
            int tempv = 0;

            System.out.print("Solution " + num + ": ");

            for (int i = 0; i < n; i++) {
                if (k % 2 == 1) {
                    tempw += w[i];
                    tempv += v[i];
                    System.out.print(i + " ");
                }
                k /= 2;
            }

            System.out.println("(Total weight: " + tempw + ","+"Total value: "+tempv+")");

            if (tempw <= c && tempv > maxv) {
                maxv = tempv;
            }
        }

        System.out.println("The maxvalue is " + maxv + ".");
    }
}

结果实现:

七.算法分析

 对于一个具有n个元素的集合,其子集数量是2^n,所以,不论生成子集的算法效率有多高,蛮力法求解0/1背包问题都会导致一个\Omega(2^n)的算法。
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值