问题描述
方法
动态规划法解决问题,我们只需要每次在加入物品的时候保证不超过容量,不超过容积的情况下不断求当前价值的最大值即可.我们创建一个三维数组,维度分别为物品序号,当前容量和当前容积,在判断是否加入新物品之前,我们需要判断加入该物品与不加该物品的价值高低,这样的话,在往后加入物品时也可以修改曾经的选择,因为我们的数组中各个物品的加或者不加的情况都已经列举出来了,直接查找即可。
#include <iostream>
#include <fstream>
#include <windows.h>
#include <iomanip>
#include <stdlib.h>
#include <ctime>
using namespace std;
void Random(){//随机产生物品的重量和价值
srand(time(0));
ofstream output("input1.txt");
cout<<"请输入背包的重量和商品的件数:";
int c,n;
cin>>c>>n;
output<<c<<" "<<n<<endl;
for(int i=0;i<n;i++){
int w=rand()%(c-1+1)+1;
int v=rand()%(c-1+1)+1;
output<<w<<" "<<v<<endl;
}
}
int main(){
Random();
ifstream input("input1.txt");
if(!input)
cout<<"打开失败!";
ofstream output("output1.txt");
int c,n;
input>>c>>n;
int w[n+1]={0},v[n+1]={0};//w表示物品的重量,v表示物品的价值
for(int i=1;i<=n;i++)
input>>w[i]>>v[i];
int V[n+1][c+1]; //B记录选择前n个物品,背包容量为c,可获得的最大价值
for(int i=0;i<=n;i++)//对B初始化
for(int j=0;j<=c;j++)
V[i][j]=0;
LARGE_INTEGER BegainTime;
LARGE_INTEGER EndTime;
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&BegainTime) ;
for(int i=1;i<=n;i++){//对物品逐个选择
for(int j=0;j<=c;j++){//背包容量从0到c
if(w[i]>j)//如果wi的重量大于了背包的剩余容量
V[i][j]=V[i-1][j];
else{
//比较选择和不选择时的情况
int V1=V[i-1][j-w[i]]+v[i];
int V2=V[i-1][j];
V[i][j]=V1>V2?V1:V2;
}
}
}
cout<<"能获得的最大价值是:"<<V[n][c]<<endl;
output<<"能获得的最大价值是:"<<V[n][c]<<endl;
QueryPerformanceCounter(&EndTime);
cout<<"运行时间:"
<<fixed << setprecision(0)<<(double)(EndTime.QuadPart-BegainTime.QuadPart)
<<"us"<<endl;
output<<"运行时间:"
<<fixed << setprecision(0)<<(double)(EndTime.QuadPart-BegainTime.QuadPart)
<<"us"<<endl;
}
算法分析
时间复杂度很明显为O(nc)