#include <iostream> using namespace std; //贪心算法解决部分背包问题 class GreedyKnapsack { private: int *weight;//物品重量 int *value;//物品价值 int numOfItems;//物品数量 int bagSpace;//背包容量 double bestValue;//最大价值 double *best;//记录每个物品放入数量 int *x;//记录按单位重量价值排序后的次序x[1]表示单位重量价值最大的序号,x[numOfItems]表示最小的序号,初始化为1,2…..numOfItems public: //构造函数 GreedyKnapsack(int numOfItems,int bagSpace) { this->numOfItems=numOfItems; this->bagSpace=bagSpace; bestValue=0; weight=new int[numOfItems+1];//物品重量 value=new int[numOfItems+1];//物品价值 best=new double[numOfItems+1];//记录物品选择情况 x=new int[numOfItems+1];//随下标递增,其中存放的物品编号的价值比重逐渐增大 for(int i=1;i<=numOfItems;i++) { x[i]=i;//初始化序号为1到n,排序后x[1:n]存储的为按单位重量价值从小到大的物品序号 best[i]=(double)0;//初始化 } } //nlgn的快速排序算法,排序的key为x[i]中序号物品的单位重量价值 void quickSort(int start,int end) { if(start<end) { int middle=partition(start,end); quickSort(start,middle); quickSort(middle+1,end); } } //划分算法,与普通快排不同在于依据x[i]中的序号,以单位重量价值进行排序,交换的也是x[i]值,通过x[i]值找到weight,value int partition(int start,int end) { int i=start; int j=end; double key=(double)(value[x[i]]/weight[x[i]]); while(true) { while((double)(value[x[i]]/weight[x[i]])<key) { ++j; } while((double)(value[x[j]]/weight[x[j]])>key) { –j; } if(i<j) { swap(i,j); ++i; –j; } else { return j; } } } //交换x[]元素算法 void swap(int i,int j) { int temp=x[i]; x[i]=x[j]; x[j]=temp; } //贪心算法完成部分背包问题 void greedyKnapsack() { quickSort(1,numOfItems);//按性价比排序 int leftSpace=bagSpace;//初始化剩余容量为背包容量 int i=numOfItems;//从第一个性价比最高的物品开始放起 while(weight[x[i]]<=leftSpace&&i>=1)//如果物品能完全放进去 { bestValue+=(double)value[x[i]];//累加最大价值 best[x[i]]=(double)1; leftSpace-=weight[x[i]]; –i; } if(i>=1)//如果物品只能放进部分 { best[x[i]]=(double)leftSpace/weight[x[i]]; bestValue+=(double)leftSpace*value[x[i]]/weight[x[i]]; } } //输入物品重量与价值 void input() { for(int i=1;i<=numOfItems;i++) { cout<<“输入第”<<i<<“个物品的重量”<<endl; cin>>weight[i]; cout<<“输入第”<<i<<“个物品的价值”<<endl; cin>>value[i]; } } //输出物品的选择情况 void display() { for(int i=1;i<=numOfItems;i++) { cout<<“第”<<i<<“个物品被选择了:”<<best[i]<<“个”<<endl; } cout<<“背包最大容纳价值”<<bestValue<<endl; } }; void main() { GreedyKnapsack test(5,50);//5个物品,背包容量50 test.input();//输入物品重量与价值 test.greedyKnapsack();//部分背包的贪心算法 test.display();//打印出物品选择情况 }
贪心算法的简单理解: 尽量满足题目的要求。
例如此题: 为了让背包装入得价值最大,那么就是背包装满时的价值最大,即平均价值最大。 所以我们对物品按单位重量价值排序,然后首先利用贪心策略将性价比最高的物品放进去,然后放次高的,一直将背包放满即可。 简单的反证:如果我们将不属于贪心解得一个物品放进去,那么此时背包的最大价值是绝对不会超过贪心解得,因为贪心解内的物品都是价值比最大的,没在贪心解内的物品的价值比都小于贪心解内的物品,所以替换之后不会比贪心解更优。