一.问题描述
【问题描述】使用动态规划算法解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<<" ";
}