贪心法:部分背包问题
2009-09-05 00:23
218 查看
因可以取物体的部分放入,故每次选择价值重量比最高的物体放入,可保证放入的价值一定最大,满足贪婪选择性质和最有子结构性质,故采用贪心算法求解:
1. 根据各个物体的价值p与重量w计算价值重量比v
2. 根据v降序排序
3. 从当前最大的v的开始,判断该物体重量是否超过背包剩余载重
4. 是则放入背包剩余载重量的物体,加上这部分的价值,跳到7
5. 否则将物体完整放入背包,加上物体的价值
6. 若还有物体未放入背包,则跳到3
7. 输出背包中物体的总价值
Code:
#include<iostream>
#include<algorithm>
using namespace std;
#define N 50 // 最多输入物体数
/***********************
* 存放背包属性的结构体
***********************/
typedef struct{
float p; // 物体的价值
float w; // 物体的重量
float v; // 物体的价值重量比
}Object;
/*******************************
* 比较函数:按v的递减顺序排序
*******************************/
bool compare(Object a, Object b){
return a.v>b.v;
}
/****************************************************************
* 求解背包问题的贪婪算法
*
* 输入:背包载重量M, 存放n个物体属性的数组instance[],物体个数n
* 输出:n个物体被装入背包的份量x[],背包中物体的最大总价
****************************************************************/
float knapsack_greedy(float m, Object instance[], float x[], int n){
int i;
float p = 0; // 总价值初始为0
/* 初始化 */
for(i=0; i<n; i++){
instance[i].v = instance[i].p / instance[i].w; // 计算物体价值重量比
x[i] = 0; // 默认放入份量为0
}
/* 对物体进行排序:按v的递减顺序 */
sort(instance,instance+n,compare);
/* 填物过程 */
for(i=0; i<n; i++){
if(instance[i].w<=m){ // 若物体重量小于等于剩余载重量
x[i] = 1; // 将物体全部装入 置x[i]为1
m -= instance[i].w; // 从剩余载重量中去掉物体的重量
p += instance[i].p; // 总价值加上物体的完整价值
}else{ // 若物体重量大于剩余载重量
x[i] = m / instance[i].w; // 置x[i]为剩余载重量/物体重量:即最大能置入的百分比
p+= x[i]*instance[i].p; // 总价值加上物体装入部分的价值
break; // 此时背包已满,可以退出循环
}
}
return p;
}
/***********************
* 打印换行符
***********************/
void printhr(){
cout<<"------------------------------------------------------------------------"<<endl;
}
int main(){
Object instance
; // n个物体的属性
float x
; // n个物体装入背包的份量(0<=x[i]<=1)
float m; // 背包的最大载重量
int n; // 物体个数
int i;
/* 输入开始 */
cout<<"请输入背包的载重量:";
cin>>m;
cout<<"请输入物体的个数:";
cin>>n;
cout<<"请输入物体的价格、重量:"<<endl;
printhr();
for(i=0; i<n; i++){
cout<<"【第"<<(i+1)<<"件物品】";
cin>>instance[i].p>>instance[i].w;
printhr();
}
/* 输入结束 */
/* 计算最大价值和各物体装入的重量 */
float maxv = knapsack_greedy(m, instance, x, n);
/* 输出开始 */
cout<<endl<<endl<<"可装入的最大价值是:"<<maxv<<endl;
printhr();
cout<<"每个物体各装入:"<<endl;
printhr();
for( i=0; i<n; i++){
cout<<"【第"<<(i+1)<<"件物品】";
cout<<"价值:"<<instance[i].p<<" 总量:"<<instance[i].w<<" 价值总量比:"<<instance[i].v<<" 放入数量:"<<x[i]*instance[i].w<<endl;
printhr();
}
/* 输出结束 */
return 0;
}
1. 根据各个物体的价值p与重量w计算价值重量比v
2. 根据v降序排序
3. 从当前最大的v的开始,判断该物体重量是否超过背包剩余载重
4. 是则放入背包剩余载重量的物体,加上这部分的价值,跳到7
5. 否则将物体完整放入背包,加上物体的价值
6. 若还有物体未放入背包,则跳到3
7. 输出背包中物体的总价值
Code:
#include<iostream>
#include<algorithm>
using namespace std;
#define N 50 // 最多输入物体数
/***********************
* 存放背包属性的结构体
***********************/
typedef struct{
float p; // 物体的价值
float w; // 物体的重量
float v; // 物体的价值重量比
}Object;
/*******************************
* 比较函数:按v的递减顺序排序
*******************************/
bool compare(Object a, Object b){
return a.v>b.v;
}
/****************************************************************
* 求解背包问题的贪婪算法
*
* 输入:背包载重量M, 存放n个物体属性的数组instance[],物体个数n
* 输出:n个物体被装入背包的份量x[],背包中物体的最大总价
****************************************************************/
float knapsack_greedy(float m, Object instance[], float x[], int n){
int i;
float p = 0; // 总价值初始为0
/* 初始化 */
for(i=0; i<n; i++){
instance[i].v = instance[i].p / instance[i].w; // 计算物体价值重量比
x[i] = 0; // 默认放入份量为0
}
/* 对物体进行排序:按v的递减顺序 */
sort(instance,instance+n,compare);
/* 填物过程 */
for(i=0; i<n; i++){
if(instance[i].w<=m){ // 若物体重量小于等于剩余载重量
x[i] = 1; // 将物体全部装入 置x[i]为1
m -= instance[i].w; // 从剩余载重量中去掉物体的重量
p += instance[i].p; // 总价值加上物体的完整价值
}else{ // 若物体重量大于剩余载重量
x[i] = m / instance[i].w; // 置x[i]为剩余载重量/物体重量:即最大能置入的百分比
p+= x[i]*instance[i].p; // 总价值加上物体装入部分的价值
break; // 此时背包已满,可以退出循环
}
}
return p;
}
/***********************
* 打印换行符
***********************/
void printhr(){
cout<<"------------------------------------------------------------------------"<<endl;
}
int main(){
Object instance
; // n个物体的属性
float x
; // n个物体装入背包的份量(0<=x[i]<=1)
float m; // 背包的最大载重量
int n; // 物体个数
int i;
/* 输入开始 */
cout<<"请输入背包的载重量:";
cin>>m;
cout<<"请输入物体的个数:";
cin>>n;
cout<<"请输入物体的价格、重量:"<<endl;
printhr();
for(i=0; i<n; i++){
cout<<"【第"<<(i+1)<<"件物品】";
cin>>instance[i].p>>instance[i].w;
printhr();
}
/* 输入结束 */
/* 计算最大价值和各物体装入的重量 */
float maxv = knapsack_greedy(m, instance, x, n);
/* 输出开始 */
cout<<endl<<endl<<"可装入的最大价值是:"<<maxv<<endl;
printhr();
cout<<"每个物体各装入:"<<endl;
printhr();
for( i=0; i<n; i++){
cout<<"【第"<<(i+1)<<"件物品】";
cout<<"价值:"<<instance[i].p<<" 总量:"<<instance[i].w<<" 价值总量比:"<<instance[i].v<<" 放入数量:"<<x[i]*instance[i].w<<endl;
printhr();
}
/* 输出结束 */
return 0;
}
相关文章推荐
- 贪心算法解决部分背包问题 在O(lgn)时间内
- 算法学习:贪心解部分背包问题
- 部分背包问题的贪心算法正确性证明
- 部分背包问题的贪心算法正确性证明
- 贪心算法解决部分背包问题
- 贪心法部分背包问题的实现
- 贪心算法解决部分背包问题(C语言,ruby)
- 部分背包问题(贪心基础)
- 贪心算法——部分背包问题(贪心策略内容)
- 【算法】贪心策略实现部分背包问题
- 贪心算法;部分背包问题;快速排序O(nlgn);贪心算法O(n);
- 经典算法6:贪心算法解决部分背包问题
- 贪心算法练习题:部分背包问题
- ACM知识点 之 贪心(4)部分背包问题
- 部分背包问题(贪心)
- 部分背包问题贪心选择性质的证明
- 步步为营(五)贪心(4)部分背包问题
- 贪心法 部分背包问题 结构体数组 FatMouse' Trade
- 部分背包问题(贪心) HDU1009
- 纯C语言:贪心部分背包问题源码