动态规划实现 01背包问题
2011-04-03 12:02
260 查看
★问题描述 给定n种物品和一背包。物品i的重量是weight[i],其价值为value[i],背包的容量为capacity。问:应该如何选择装入背包的物品(这些物品每样只有一件,要么被装入要么被留下),使得装入背包中物品的总价值最大?
★格式输入 Capacity numGoodsweight[1] value[1]weight[2] value[2]......
★格式输出 第一行1个数字,表示总最大价值。
第二行共n个数字,表示所选的物品。
★样例输入 10 5
2 6
2 3
6 5
5 4
4 6
★样例输出 15
1 2 5
★算法设计(包括算法设计过程中相关内容的说明、数据结构的选择、 算法详细描述及算法分析):
●1.设计说明:
1.1最优子结构性质:设(x1,x2,...,xn)是所给0-1背包问题的一个最优解,则(x1,x2,...,xn-1)是下列子问题的最优解。
1.2递归公式:
m(i,j)是背包容量为j,可选择前i 个物品时0-1背包问题的最优值,由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下:
m(i,j) = m(i-1,j) // 0<= j <weight[i];
max{m(i-1,j),m(i-1,j-weight[i])+value[i]} //j >= weight[i]
●2.算法设计:
●2.1数据结构:
int capacity; //背包容量
int numGoods; //物品数量
int max[MAX_NUM][MAX_CAPACITY];//记录递归中间结果
int weight[MAX_NUM]; //物品重量
int value[MAX_NUM]; //物品价值
int chose[MAX_NUM]; //记录物品是否被选中,为1则选中,为0未被选中
int maxValue; //背包中物品的最大价值
●2.2算法描述:
input(numGoods,weight,value);//读入数据
printInitData(capacity,numGoods,weight,value,max);//打印初始化后的数据
dKnap(maxValue,max,capacity,numGoods,weight,value); //求解背包问题
traceBack(chose,numGoods,capacity,max);//判断物品是否被选中
printResult(numGoods,capacity,maxValue,max,chose);//打印计算结果
//计算并保存最优子结构
for(int i = 1; i <= numGoods; i++)
{
for(int j = 1; j <= capacity; j++)
{
if(j < weight[i])
m(i,j) = m(i-1,j);
else if(j >= weight[i])
m(i,j) = max{m(i-1,j),m(i-1,j-weight[i])+value[i]};
}
}
//判断物品是否被选中
if(max[i][capacity] == max[i-1][capacity])
chose[i] = 0;
else
{
chose[i] = 1;
capacity -= weight[i];
}
●2.3算法分析
Dknap()函数的复杂度为O(nc) 其中c = capacity
traceBack()复杂度为O(n)
本算法的最坏时间复杂度为:O(nc)
最坏空间复杂度为:O(nc)
★格式输入 Capacity numGoodsweight[1] value[1]weight[2] value[2]......
★格式输出 第一行1个数字,表示总最大价值。
第二行共n个数字,表示所选的物品。
★样例输入 10 5
2 6
2 3
6 5
5 4
4 6
★样例输出 15
1 2 5
★算法设计(包括算法设计过程中相关内容的说明、数据结构的选择、 算法详细描述及算法分析):
●1.设计说明:
1.1最优子结构性质:设(x1,x2,...,xn)是所给0-1背包问题的一个最优解,则(x1,x2,...,xn-1)是下列子问题的最优解。
1.2递归公式:
m(i,j)是背包容量为j,可选择前i 个物品时0-1背包问题的最优值,由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下:
m(i,j) = m(i-1,j) // 0<= j <weight[i];
max{m(i-1,j),m(i-1,j-weight[i])+value[i]} //j >= weight[i]
●2.算法设计:
●2.1数据结构:
int capacity; //背包容量
int numGoods; //物品数量
int max[MAX_NUM][MAX_CAPACITY];//记录递归中间结果
int weight[MAX_NUM]; //物品重量
int value[MAX_NUM]; //物品价值
int chose[MAX_NUM]; //记录物品是否被选中,为1则选中,为0未被选中
int maxValue; //背包中物品的最大价值
●2.2算法描述:
input(numGoods,weight,value);//读入数据
printInitData(capacity,numGoods,weight,value,max);//打印初始化后的数据
dKnap(maxValue,max,capacity,numGoods,weight,value); //求解背包问题
traceBack(chose,numGoods,capacity,max);//判断物品是否被选中
printResult(numGoods,capacity,maxValue,max,chose);//打印计算结果
//计算并保存最优子结构
for(int i = 1; i <= numGoods; i++)
{
for(int j = 1; j <= capacity; j++)
{
if(j < weight[i])
m(i,j) = m(i-1,j);
else if(j >= weight[i])
m(i,j) = max{m(i-1,j),m(i-1,j-weight[i])+value[i]};
}
}
//判断物品是否被选中
if(max[i][capacity] == max[i-1][capacity])
chose[i] = 0;
else
{
chose[i] = 1;
capacity -= weight[i];
}
●2.3算法分析
Dknap()函数的复杂度为O(nc) 其中c = capacity
traceBack()复杂度为O(n)
本算法的最坏时间复杂度为:O(nc)
最坏空间复杂度为:O(nc)
//============================================= //dKNAP.cpp //0/1 Knapsack problem //动态规划 //by leo //3.28.2011 //============================================= #include<iostream> #include<fstream> #include<string> using namespace std; //--------------------------------------------- const int MAX_NUM = 1000;//最大物品数 const int MAX_CAPACITY = 10000; //最大容量 const string outFileName = "output.txt"; //输出文件名称 int capacity; //背包容量 int numGoods; //物品数量 int max[MAX_NUM][MAX_CAPACITY];//记录递归中间结果 int weight[MAX_NUM]; //物品重量 int value[MAX_NUM]; //物品价值 int chose[MAX_NUM]; //记录物品是否被选中,为1则选中,为0未被选中 int maxValue; //背包中物品的最大价值 //--------------------------------------------- void input(int& numGoods,int* weight,int* value); //读入数据 void printInitData(int capacity,int numGoods,const int* weight,const int* value,int max[][MAX_CAPACITY]); //打印初始化后的数据 void dKnap(int& maxValue,int max[][MAX_CAPACITY],int capacity,int numGoods,const int* weight,const int* value); //求解背包问题 void traceBack(int* chose,int numGoods,int capacity,int max[][MAX_CAPACITY]); //判断物品是否被选中 void printMax(int numGoods,int capacity,int max[][MAX_CAPACITY]); //打印最优值数组 void printResult(int numGoods,int capacity,int maxValue,int max[][MAX_CAPACITY],int* chose); //打印计算结果 //--------------------------------------------- int main() { input(numGoods,weight,value); printInitData(capacity,numGoods,weight,value,max); dKnap(maxValue,max,capacity,numGoods,weight,value); traceBack(chose,numGoods,capacity,max); printResult(numGoods,capacity,maxValue,max,chose); system("pause"); return 0; } //--------------------------------------------- //根据用户输入,读取相应文件内容并将之保存到数组中 //--------------------------------------------- void input(int& numGoods,int* weight,int* value) { string str; cout << "Please input the input file name" << "(input_assign02_00.txt~input_assign02_01.txt):/n"; cin >> str; ifstream fin(str.c_str()); if(!fin) { cout << "no such file,please check the file name!" <<endl; exit(0); } fin >> capacity >> numGoods; for(int i = 1; i <= numGoods, fin >> weight[i] >> value[i]; i++); } //--------------------------------------------- //打印初始化后的数据 //--------------------------------------------- void printInitData(int capacity,int numGoods,const int* weight,const int* value,int max[][MAX_CAPACITY]) { cout << "capacity : " << capacity <<endl; cout << "numGoods : " << numGoods <<endl; cout << "weight " << "value "<<endl; for(int j = 1; j <= numGoods; j++) cout << weight[j] << " " << value[j] <<endl; cout << "before caculate:/n"; printMax(numGoods,capacity,max); } //--------------------------------------------- //将计算所得最优值保存在数组中 //--------------------------------------------- void dKnap(int& maxValue,int max[][MAX_CAPACITY],int capacity,int numGoods,const int* weight,const int* value) { for(int n = 0; n <= capacity; n++) max[0] = 0; for(int m = 0; m <= numGoods; m++) max[m][0] = 0; for(int i = 1; i <= numGoods; i++) { for(int j = 1; j <= capacity; j++) { if(j < weight[i]) max[i][j] = max[i-1][j]; else if(j >= weight[i]) { int maxNoI = max[i-1][j]; int maxHavI = max[i-1][j-weight[i]] + value[i]; max[i][j] = maxNoI > maxHavI ? maxNoI : maxHavI; } } } maxValue = max[numGoods][capacity]; } //--------------------------------------------- //判断物品是否被选中 //选中:chose[i] = 1,未选中:chose[i] = 0; //--------------------------------------------- void traceBack(int* chose,int numGoods,int capacity,int max[][MAX_CAPACITY]) { for(int i = numGoods; i > 0; i--) { if(max[i][capacity] == max[i-1][capacity]) chose[i] = 0; else { chose[i] = 1; capacity -= weight[i]; } } } //--------------------------------------------- //打印最优值数组 //--------------------------------------------- void printMax(int numGoods,int capacity,int max[][MAX_CAPACITY]) { for(int i = 0; i <= numGoods; i++) { for(int j = 0; j <= capacity; j++) { cout << max[i][j] << " "; } cout << endl; } } //--------------------------------------------- //打印计算结果 //--------------------------------------------- void printResult(int numGoods,int capacity,int maxValue,int max[][MAX_CAPACITY],int* chose) { ofstream fout(outFileName.c_str()); cout << "after caculate:/n"; printMax(numGoods,capacity,max); cout << "maxValue: " << maxValue <<endl; fout << maxValue <<endl; cout << "the Goods that be chose:/n"; for(int i = 1; i <= numGoods; i++) { if(chose[i] == 1) { cout << i << " "; fout << i << " "; } } } //=============================================
相关文章推荐
- 动态规划解决01背包问题(java实现)
- nyoj289 苹果 典型01背包问题(动态规划)思路及实现过程
- Java-01背包问题-动态规划-递归和非递归实现
- 01背包问题(动态规划)python实现
- 背包问题——“01背包”详解及实现(包含背包中具体物品的求解)
- 动态规划_01背包问题_Java实现
- 01背包问题(动态规划)
- 01背包问题(java实现)
- 动态规划——01背包问题
- 动态规划之01背包问题
- 01背包问题(动态规划)
- 01背包问题(回溯法)python实现
- 01背包问题(Java实现)
- 01背包问题python递归实现
- 动态规划之01背包问题
- java实现动态规划求解矩阵连乘问题
- 算法_动态规划_01背包问题(重量为浮点型)
- 动态规划经典问题Java实现
- 背包问题——“01背包”及“完全背包”装满背包的方案总数分析及实现
- c++实现0-1背包问题完整源码(动态规划实现)