0-1背包问题

一.问题描述
【问题描述】使用动态规划算法解0-1背包问题,使得选择合适物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
【输入形式】在屏幕上输入背包容量、物品数量、每件物品价值和重量。
【输出形式】最优解时所选物品的价值总和及其编号。
【样例输入】
10
5
6 3 5 4 6
2 2 6 5 4
【样例输出】
15
1 2 5
二.算法思路
dp数组m[i][j]表示背包容量为j,可选择物品为i,i+1…,n时背包问题的最优值。对于每一件物品i来讲,如果当前背包容量大于等于该件物品重量的话都有选或者不选两种选择如果不选则有m[i][j]=m[i+1][j],如果选该物品则有m[i][j]=m[i+1][j-wi]+vi,选择两者较大的,自底向上依次求解。
状态转移方程:在这里插入图片描述

三.源代码

#include<bits/stdc++.h>
using namespace std;
int m[1000][1000]; 
//m[i][j]表示背包容量为j,可选择物品为i,i+1...,n时背包问题的最优值
//m[1][c]的值就是背包问题的最优值 
int ans[1000];
void KNAPSACK(int value[],int weight[],int c,int n){
	int jmax1=min(weight[n]-1,c);
	for(int i=0;i<=jmax1;i++)
		m[n][i]=0;
	for(int i=weight[n];i<=c;i++) 
		m[n][i]=value[n];
	for(int i=n-1;i>=2;i--){
		int jmax2=min(weight[i]-1,c);
		for(int j=0;j<=jmax2;j++)
			m[i][j]=m[i+1][j];
		for(int k=weight[i];k<=c;k++)
			m[i][k]=max(m[i+1][k],m[i+1][k-weight[i]]+value[i]);
	}
	m[1][c]=m[2][c];
	if(c>=weight[1])
		m[1][c]=max(m[2][c],m[2][c-weight[1]]+value[1]);
}
void TRACEBACK(int weight[],int c,int n){
	for(int i=1;i<=n-1;i++){
		if(m[i][c]==m[i+1][c])//该物品没有被选中 
			ans[i]=0;
		else{
			ans[i]=1;
			c=c-weight[i];
		}
	}
	if(m[n][c]>0)//如果m[n][c]>0说明第n个物品被选中 
		ans[n]=1;
	else
		ans[n]=0;
}
int main(){
	int capacity;
	int cnt;
	int value[30];
	int weight[30];
	cin>>capacity;//背包容量 
	cin>>cnt;//物品数量 
	for(int i=1;i<=cnt;i++)
		cin>>value[i];//物品价值 
	for(int i=1;i<=cnt;i++)
		cin>>weight[i];//物品重量 
	KNAPSACK(value,weight,capacity,cnt);
	TRACEBACK(weight,capacity,cnt);
	cout<<m[1][capacity]<<endl; 
	for(int i=1;i<=cnt;i++)
		if(ans[i])
			cout<<i<<" ";	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值