趣味算法------单一背包问题(01背包问题)贪心算法解决

目录

​编辑

前言

例题

题目描述

输入输出格式

解题思路

具体代码

C语言代码

python代码

总结


前言

单一背包问题(0-1 Knapsack Problem)是组合优化中的一个经典问题,它可以形式化为:给定一组物品,每个物品都有一个重量和一个价值,目标是选择一些物品放入背包中,使得背包中物品的总价值最大,同时不超过背包的最大承重限制。在这个问题中,每个物品只能选择放或不放,不能分割。

解决单一背包问题的方法包括动态规划、回溯算法和分支限界法等。动态规划是解决这类问题的常用方法,它通过构建一个二维数组来存储子问题的解,并使用状态转移方程来填充这个数组。状态转移方程通常表示为 dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]),其中 dp[i][j] 表示前 i 个物品放入容量为 j 的背包中所能获得的最大价值,w[i] 和 v[i] 分别表示第 i 个物品的重量和价值。

在实际应用中,单一背包问题可以模拟旅行行李打包、投资组合选择、货物装载与运输、项目选择与管理、供应链管理、能源管理、课程安排和紧急救援物资分配等场景。

例题

题目描述

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。
第 i 件物品的体积是 vi ,价值是 wi 。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入输出格式

输入格式
第一行两个整数N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N 行,每行两个整数 vi wi,用空格隔开,分别表示第 i 件物品的体积和价值。
输出格式
一个非负整数,代表结果。

输入输出样例1
输入
4 5
1 2
2 4
3 4
4 5
输出
8

输入输出样例2
输入
1 2
2 2
输出
2

解题思路

  1. 初始化:首先,代码定义了背包的容量V和物品的数量N。然后,它为物品的重量和价值分配了动态数组weightsvalues,以及一个二维数组lst来存储动态规划过程中的状态值。

  2. 输入读取:代码使用scanf函数从标准输入读取物品的数量、背包容量以及每个物品的重量和价值。

  3. 动态规划填充:代码通过两层嵌套循环来填充动态规划数组lst。外层循环遍历物品,内层循环遍历背包的容量。对于每个容量和每个物品,代码检查当前物品是否可以放入背包中(即当前容量是否大于或等于该物品的重量)。如果可以,代码计算放入当前物品和不放入当前物品两种情况下的最大价值,并更新lst数组中相应位置的值。

  4. 结果输出:填充完成后,代码通过printf函数输出背包的最大价值,即lst[N][V]

具体代码

C语言代码

​
#include<stdio.h>
#include<stdlib.h>
#define maxlen 100
int main(void)
{
	int N, V;
	scanf("%d%d", &N, &V);
	int lst[maxlen][maxlen] = { 0 };
	int* weights = (int*)malloc(N * sizeof(int));
	int* values = (int*)malloc(V * sizeof(int));
	for (int i = 0; i < N; i++)
	{
		int s, r;
		scanf("%d%d", &s, &r);
		weights[i] = s;
		values[i] = r;
	}
	for(int i = 1;i<N+1;i++)
		for (int j = 1; j < V + 1; j++)
		{
			if (j < weights[i - 1])
				lst[i][j] = lst[i - 1][j];
			else
			{
				int datas1 = lst[i - 1][j];
				int datas2 = lst[i - 1][j - weights[i - 1]] + values[i - 1];
				
                if (datas1 > datas2)
					lst[i][j] = datas1;
				else
					lst[i][j] = datas2;
                
                lst[i][j]=(datas1>datas2)?datas1:datas2;
			}
		}
	printf("%d", lst[N][V]);
		
	return 0;
	
}

​

python代码

N,V = [int(i) for i in input().split()]
lst = []
weights = []
values = []
for i in range(N):
    w,v = [int(i) for i in input().split()]
    weights.append(w)
    values.append(v)
for i in range(N+1):
    lst.append([0]*(V+1))
for i in range(1,N+1):
    for j in range(1,V+1):
        if j<weights[i-1]:
            lst[i][j] = lst[i-1][j]
        else:
            datas1 = lst[i-1][j]
            datas2 = lst[i-1][j-weights[i-1]]+values[i-1]
            lst[i][j] = max(datas1,datas2)
print(lst[N][V])

总结

单一背包问题是组合优化问题中的一个经典问题,它可以通过动态规划算法高效解决。在这个问题中,目标是选择一组物品放入背包中,使得背包的总价值最大,同时不超过背包的容量限制。动态规划算法通过构建一个二维状态数组来存储子问题的最优解,并通过状态转移方程递归地求解每个子问题,最终得到整个问题的最优解。

动态规划解决单一背包问题的关键在于定义合适的状态和状态转移方程。状态通常定义为dp[i][j],表示前i个物品放入容量为j的背包中所能获得的最大价值。状态转移方程为dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]),其中w[i]v[i]分别是第i个物品的重量和价值。如果当前背包容量不足以容纳第i个物品,则状态转移方程简化为dp[i][j] = dp[i-1][j]

动态规划算法的时间复杂度为O(N*V),其中N是物品的数量,V是背包的容量。空间复杂度也是O(N*V),但可以通过使用一维数组进行空间优化,将空间复杂度降低到O(V)

在实际应用中,动态规划不仅能够解决单一背包问题,还可以扩展到完全背包问题、多重背包问题等变体。动态规划的思想在解决这类优化问题时展现了其强大的能力,通过将大问题分解为小问题并存储子问题的解,动态规划避免了重复计算,提高了算法效率。

相关推荐
梧桐树04294 小时前
python常用内建模块:collections
python
Dream_Snowar4 小时前
速通Python 第三节
开发语言·python
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子5 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
蓝天星空5 小时前
Python调用open ai接口
人工智能·python
Lenyiin5 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
jasmine s5 小时前
Pandas
开发语言·python