说明
此处代码均为本人亲自完成,复制可直接运行。因为内容较多的原因,再此不做详细介绍。本人QQ:2422380414(邮箱同号),若有不足或是疑问欢迎联系本人!
蛮力法
#include <iostream>
using namespace std;
int weight[100],value[100]; //物品重量和价值
int Path[100],path[100]; //最终路径,与当前路径
int W; //背包容量
int N; //物品个数
int Max; //最大价值
int V; //当前价值
int w; //当前重量
int func(int i){
if(i>=N){
if(V>Max&&w+value[i]<=W){
Max=V;
for(int i=0;i<N;i++)
Path[i]=path[i];
}
return Max;
}
//放入背包
w+=weight[i];
V+=value[i];
path[i]=1;
func(i+1);
//不放入背包
w-=weight[i];
V-=value[i];
path[i]=0;
func(i+1);
return Max;
}
int main(){
cout<<"请输入物品个数:";
cin>>N;
cout<<"请输入背包容量:";
cin>>W;
cout<<"请依次输入每个物品的重量和价值:"<<endl;
for(int i=0;i<N;i++)
cin>>weight[i]>>value[i];
cout<<"最大价值:"<<func(0)<<endl;
cout<<"物品存放详情:"<<endl;
for(int i=0;i<N;i++)
cout<<Path[i]<<" ";
return 0;
}
动态规划
#include <iostream>
using namespace std;
void func(int weight[],int value[],int W,int n){
//Dp[i][j],表示背包容量为j时,前i个物品能装入背包的最大价值。
int Dp[n+1][W+1];
//初始第一列,第一行为0
for(int i=0;i<=n;i++){
Dp[i][0]=0;
}
for(int j=0;j<=W;j++){
Dp[0][j]=0;
}
//计算最大价值
for(int i=1;i<=n;i++){
for(int j=1;j<=W;j++){
if(j<weight[i-1]){
Dp[i][j]=Dp[i-1][j];
}else{
Dp[i][j]=max(Dp[i-1][j],Dp[i-1][j-weight[i-1]]+value[i-1]);
}
}
}
//输出选择情况
int path[n];
for(int i=n,j=W;i>0;i--){
if(Dp[i][j]>Dp[i-1][j]){
path[i-1]=1;
j=j-weight[i-1];
}else{
path[i-1]=0;
}
}
for(int i=0;i<n;i++)
cout<<path[i]<<" ";
cout<<endl;
cout<<"最大价值为:"<<Dp[n][W]<<endl;
}
int main(){
int n,W;
cout<<"请输入物品个数:";
cin>>n;
int weight[n],value[n];
cout<<"请依次输入"<<n<<"个物品的质量和价值:"<<endl;
for(int i=0;i<n;i++){
cin>>weight[i]>>value[i];
}
cout<<"请输入背包容量:";
cin>>W;
func(weight,value,W,n);
return 0;
}
回溯
#include <iostream>
using namespace std;
int Path[100]; //Path是最终路径,path是当前路径。
void func(int weight[],int value[],int W,int n,int path[],int &Max,int V,int c,int start){
//V表示当前价值,c表示当前重量,Max表示最终得到的最大结果
if(c<=W){
//Max=max(Max,V);
if(V>Max){
Max=V;
for(int i=0;i<n;i++)
Path[i]=path[i]; //保存存放路径
}
for(int i=start;i<n;i++){
c+=weight[i];
V+=value[i];
path[i]=1;
func(weight,value,W,n,path,Max,V,c,i+1);
c-=weight[i];
V-=value[i];
path[i]=0;
}
}
}
int main(){
int n,W;
cout<<"请输入物品个数:";
cin>>n;
int weight[n],value[n];
int path[n]={0};//用来记录取最大值时背包所放物品
cout<<"请依次输入"<<n<<"个物品的质量和价值:"<<endl;
for(int i=0;i<n;i++){
cin>>weight[i]>>value[i];
}
cout<<"请输入背包容量:";
cin>>W;
int Max=0;
func(weight,value,W,n,path,Max,0,0,0);
cout<<"背包能装最大价值:"<<Max<<endl;
cout<<"物品存放详情:"<<endl;
for(int i=0;i<n;i++)
cout<<Path[i]<<" ";
return 0;
}
分支界限
#include <iostream>
#include <cmath>
using namespace std;
int Bound(int* Weights,int* Values,int n,int W,int num,int current_w,int current_v){
int i=num+1;
for(;i<n;i++){
if(current_w+Weights[i]<W){
current_v+=Values[i];
current_w+=Weights[i];
}else{
current_v+=(Values[i]/Weights[i])*(W-current_w);
current_w=W;
return current_v;
}
}
return current_v;
}
int* fun(int *Weights,int* Values,int W,int n){
int *X=new int[n];
int *Y=new int[n];
int Weight=0;
int Profit=0;
int current_w=0,current_v=0;
int i=0;
while(true){
while(i<n&¤t_w+Weights[i]<=W){
X[i]=1;
current_v+=Values[i];
current_w+=Weights[i];
i++;
}
//如果由于i==n结束,说明神度搜索到最底层了
if(i>=n){
Weight=current_w;
Profit=current_v;
i=n;
for(int i=0;i<n;i++){
Y[i]=X[i];
}
} else{
//第i个物品放不下
X[i]=0;
}
//如果不能获得更大的价值,舍弃当前点 ,进行回溯
while(Bound(Weights,Values,n,W,i,current_w,current_v)<=Profit){
while(i!=0&&X[i]!=1){
i--;
}
if(i==0){
cout<<"最大价值:"<<Profit<<endl;
return Y;
}
X[i]=0;
current_v-=Values[i];
current_w-=Weights[i];
}
i++;
}
}
int main(){
int n,W;
cout<<"输入物品个数:";
cin>>n;
cout<<"请输入背包容量:";
cin>>W;
int Weight[n];
int Value[n];
int *path;
cout<<"请依次输入n个物品的质量和价值(V/W从大到小):"<<endl;
for(int i=0;i<n;i++){
cin>>Weight[i]>>Value[i];
}
path=fun(Weight,Value,W,n);
for(int i=0;i<n;i++)
cout<<path[i]<<" ";
return 0;
}