完全背包问题

19 篇文章 1 订阅

完全背包问题的阐述:

题目描述
设有n种物品,每种物品有一个重量及一个价值。但每种物品的数量是无限的,同时有一个背包,最大载重量为M,今从n种物品中选取若干件(同一种物品可以多次选取),使其重量的和小于等于M,而价值的和为最大。
输入
第一行:两个整数,M(背包容量,M≤200)和N(物品数量,N≤30);

第2…N+1行:每行二个整数Wi,Ci,表示每个物品的重量和价值。

输出
仅一行,一个数,表示最大总价值。
样例输入
10 4
2 1
3 3
4 5
7 9
样例输出
max=12

完全背包问题跟01背包问题的区别在于:
01背包问题的物品只能选择一个,那么只存在选与不选的区别。
完全背包的同一物品可以选多个,但是重量不能超过背包的容量。

完全背包背包问题可分为两大类:
一.当前物品的重量超过背包容量(不选)
二.选择当前物品
{
选择0件
选择1件

选择k件
}
求选择物品件数的最大值为当前的结果

设f[i][j]为选择当前i个物品,最大容量为j的情况下,能装入的最大价值,选择的物品件数为k,第i件物品的价值和重量分别为v[i],w[i]。
选择k件物品后的价值f[i][j]为 f[i][j] = f[i-1][j-w[i]*k]+v[i]*k

状态转移方程如下图所示:
在这里插入图片描述

代码实现:

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

const int MAXCAPACITH = 202; //背包最大容量
const int MAXNUM = 32;  //最大物品数量
int w[MAXNUM];  //物品的重量
int v[MAXNUM];  //物品的价值
int f[MAXNUM][MAXCAPACITH]; //选择物品i,最大容量为j的情况下,最大能装入的物品价值

void complete_backpack(int M, int N)
{
	for (int i = 1; i <= N; i++)
	{
		for (int j = 1; j <= M; j++)
		{
			if (w[i] > j)
			{
				f[i][j] = f[i - 1][j];
			}
			else
			{
				int max = f[i - 1][j];
				for (int k = 0; (j - w[i] * k) >= 0; k++)  //选择 k = 0, 1, 2, 3...中能产生最大价值的物品数量k
				{
					if (f[i - 1][j - w[i] * k] + v[i] * k > max)
					{
						max = f[i - 1][j - w[i] * k] + v[i] * k;
					}
				}
				f[i][j] = max;
			}
		}
	}
	printf("max=%d\n", f[N][M]);
}

int main()
{
	int M, N;
	scanf("%d %d",&M, &N);
	for (int i = 1; i <= N; i++)
	{
		scanf("%d %d", &w[i], &v[i]);
	}
	complete_backpack(M, N);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值