趣味算法------单一背包问题(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)

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

相关推荐
小码的头发丝、25 分钟前
Django中ListView 和 DetailView类的区别
数据库·python·django
为什么这亚子38 分钟前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
1 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
~yY…s<#>1 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
Chef_Chen1 小时前
从0开始机器学习--Day17--神经网络反向传播作业
python·神经网络·机器学习
千澜空2 小时前
celery在django项目中实现并发任务和定时任务
python·django·celery·定时任务·异步任务
斯凯利.瑞恩2 小时前
Python决策树、随机森林、朴素贝叶斯、KNN(K-最近邻居)分类分析银行拉新活动挖掘潜在贷款客户附数据代码
python·决策树·随机森林
幸运超级加倍~2 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan201903132 小时前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法2 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法