1.定义
下面标黄的都是贪心很重要的点
2.贪心的基本思想
贪心的具体实施方式有以下两种:
3.例子:贪心解决0-1背包问题
该问题隐含了一个条件,每个物品只有一件,也就是限定了每件物品只能选择0个或者1个,因此称之为0-1背包问题
贪心的策略总共有三种:
第一种:
根据物品价值选择,每次都选价值最高的物品。
根据这个策略,最终选择装入背包的物品编号是4、2、6、5,此时包中物品总重量是130,总价值是165
第二种:
根据物品重量选择,每次都选择重量最轻的物品。
根据这个策略,最终选择装入背包的物品编号依次是6、7、2、1、5,此时包中物品总重量是140,总价值是155
第三种:
定义一个价值密度的概念,每次选择都选价值密度最高的物品。
C++封装的,大牛还是叼
// knapsack.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
//物品的两个属性:重量和价值
typedef struct tagObject
{
int weight;
int price;
int status; //0:未选中;1:已选中;2:已经不可选
}OBJECT;
//背包问题的两个属性:一个是可选物品列表,一个是背包总的称重量
typedef struct tagKnapsackProblem
{
std::vector<OBJECT> objs;
int totalC;
}KNAPSACK_PROBLEM;
typedef int (*SELECT_POLICY)(std::vector<OBJECT>& objs, int c);
int Choosefunc1(std::vector<OBJECT>& objs, int c)
{
int index = -1;
int mp = 0;
for(int i = 0; i < static_cast<int>(objs.size()); i++)
{
if((objs[i].status == 0) && (objs[i].price > mp))
{
mp = objs[i].price;
index = i;
}
}
return index;
}
int Choosefunc2(std::vector<OBJECT>& objs, int c)
{
int index = -1;
int mw = 10000;
for(int i = 0; i < static_cast<int>(objs.size()); i++)
{
if((objs[i].status == 0) && (objs[i].weight < mw))
{
mw = objs[i].weight;
index = i;
}
}
return index;
}
int Choosefunc3(std::vector<OBJECT>& objs, int c)
{
int index = -1;
double ms = 0.0;
for(int i = 0; i < static_cast<int>(objs.size()); i++)
{
if(objs[i].status == 0)
{
double si = objs[i].price;
si = si / objs[i].weight;
if(si > ms)
{
ms = si;
index = i;
}
}
}
return index;
}
void PrintResult(std::vector<OBJECT>& objs)
{
int totalW = 0;
int totalP = 0;
for(int i = 0; i < static_cast<int>(objs.size()); i++)
{
if(objs[i].status == 1)
{
totalW += objs[i].weight;
totalP += objs[i].price;
std::cout << "object " << i + 1 << ": weight=" << objs[i].weight <<
", price=" << objs[i].price << std::endl;
}
}
std::cout << "total weight : " << totalW << ", total price : " << totalP << std::endl;
}
//贪心的步骤:子问题的分解和选择策略
//spFunc参数是选择策略函数的接口,通过替换这个参数可以得到三种贪心策略
void GreedyAlgo(KNAPSACK_PROBLEM *problem, SELECT_POLICY spFunc)
{
int idx;
int ntc = 0;
//spFunc 每次选最符合策略的那个物品,选后再检查
while((idx = spFunc(problem->objs, problem->totalC - ntc)) != -1)
{
//所选物品是否满足背包承重要求?
if((ntc + problem->objs[idx].weight) <= problem->totalC)
{
problem->objs[idx].status = 1;
ntc += problem->objs[idx].weight;
}
else
{
//不能选这个物品了,做个标记后重新选
problem->objs[idx].status = 2;
}
}
PrintResult(problem->objs);
}
const int MIN=0x80000000;
const int N=7; //物品数量
const int V=150; //背包容量
int f[N+1][V+1];
int Package(int *W,int *C,int N,int V)
{
int i,j;
memset(f,0,sizeof(f)); //初始化为0
for(i=0;i<=N;i++)
for(j=1;j<=V;j++) //此步骤是解决是否恰好满足背包容量,
f[i][j]=MIN; //若“恰好”满足背包容量,即正好装满背包,则加上此步骤,若不需要“恰好”,则初始化为0
for(i=1;i<=N;i++)
for(j=C[i];j<=V;j++)
{
f[i][j]=(f[i-1][j]>f[i-1][j-C[i]]+W[i])?f[i-1][j]:(f[i-1][j-C[i]]+W[i]);
std::cout<<"f["<<i<<"]["<<j<<"]="<<f[i][j]<<std::endl;
}
return f[N][V];
}
void DPAlgo()
{
int W[8]={0,10,40,30,50,35,40,30}; //物品权重
int C[8]={0,35,30,60,50,40,10,25}; //物品大小
int result=Package(W,C,N,V);
if(result>0)
{
std::cout<<std::endl;
std::cout<<"the opt value:"<<result<<std::endl;
int i=N,j=V;
while(i)
{
if(f[i][j]==(f[i-1][j-C[i]]+W[i]))
{
std::cout<<i<<":"<<"w="<<W[i]<<",c="<<C[i]<<std::endl;
j-=C[i];
}
i--;
}
}
else
std::cout<<"can not find the opt value"<<std::endl;
}
OBJECT objects[] = { {35,10,0}, {30,40,0}, {60,30,0}, {50,50,0},
{40,35,0}, {10,40,0}, {25,30,0} };
int main(int argc, char* argv[])
{
KNAPSACK_PROBLEM problem;
problem.objs.assign(objects, objects + 7);
problem.totalC = 150;
//GreedyAlgo(&problem, Choosefunc1);
//GreedyAlgo(&problem, Choosefunc2);
//GreedyAlgo(&problem, Choosefunc3);
DPAlgo();
return 0;
}
需要说明的有:
1)从主函数看起,首先是初始化数据的输入,然后是 GreedyAlgo(&problem, Choosefunc1);这里用了个typedef int (*SELECT_POLICY)(std::vector<OBJECT>& objs, int c);(*SELECT_POLICY)的指针函数来表示选择不同的Choosefunc1、Choosefunc2、Choosefunc3.
2)不同的Choosefunc的输入参数包括:结构体数组以及int c,他们的返回值都是index序号,用在void GreedyAlgo()的idx中,由于是0-1背包问题,在下面的结构体成员变量的int status中来表示三种选择状态,这也在void GreedyAlgo()是有所体现的。
typedef struct tagObject
{
int weight;
int price;
int status; //0:未选中;1:已选中;2:已经不可选
}OBJECT;
OBJECT结构体枚举,用在了main的输入
OBJECT objects[] = { {35,10,0}, {30,40,0}, {60,30,0}, {50,50,0},
{40,35,0}, {10,40,0}, {25,30,0} };
结果展示:
GreedyAlgo(&problem, Choosefunc1);
GreedyAlgo(&problem, Choosefunc2)
GreedyAlgo(&problem, Choosefunc3)
DP的话先留一下