贪心算法背包问题

#include

#include

using namespace std;

struct good//表示物品的结构体

{

double p;//价值

double w;//重量

double r;//价值与重量的比

}a[2000];

double s,value,m;

int i,n;

bool bigger(good a,good b)

{

return a.r>b.r;

}

int main()

{

scanf("%d",&n);//物品个数

for (i=0;i

{

scanf("%lf%lf",&a[i].w,&a[i].p);

a[i].r=a[i].p/a[i].w;

}

sort(a,a+n,bigger);//调用sort排序函数,你大概不介意吧,按照价值与重量比排序贪心 scanf("%lf",&m);//读入包的容量m

s=0;//包内现存货品的重量

value=0;//包内现存货品总价值

for (i=0;i

{

value+=a[i].p;

s+=a[i].w;

}

printf("The total value in the bag is %.2lf.\n",value);//输出结果

return 0;

}

贪心法是一种改进了的分级处理方法。用贪心法设计算法的特点是一步一步地进行,根据某个优化测度(可能是目标函数,也可能不是目标函数),每一步上都要保证能获得局部最优解。每一步只考虑一个数据,它的选取应满足局部优化条件。若下一个数据与部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加为止。这种能够得到某种度量意义下的最优解的分级处理方法称为贪心法。

选择能产生问题最优解的最优度量标准是使用贪心法的核心问题。

假定有n个物体和一个背包,物体i 有质量wi,价值为pi,而背包的载荷能力为M。若将物体i的一部分xi(10,1

要想得到最优解,就要在效益增长和背包容量消耗两者之间寻找平衡。也就是说,总应该把那些单位效益最高的物体先放入背包。

在实现算法的程序中,实现算法的核心程序倒没碰到很大的问题,然而实现寻找最优度量标准程序时麻烦不断!

在寻找最优度量标准时,大致方向是用冒泡排序算法。也就是根据p[i]/w[i]的大小来对w[i]来排序。

在直接用此算法时,可以有如下的一段代码:

//根据效益tempArray[i]对重量w[i]排序,为进入贪心算法作准备

1 void sort(float tempArray[], flaot w[], int n)

2 {

3 int i = 0, j = 0;

4 int index = 0;

5

6 //用类似冒泡排序算法,根据效益p[i]/w[i]对w[i]排序

7 for (i = 0; i

8 {

9 float swapMemory = 0;

10 float temp;

11

12 temp = tempArray[i];

13 index = i;

14

15 for (j = i + 1; j

16 {

17 if (temp

18 {

19 temp = tempArray[j];

20 index = j;

21 }

22 }

23

24 //对w[i]排序

25 swapMemory = w[index];

26 w[index] = w[i];

27 w[i] = swapMemory;

28 }

29

30 return;

31 }

然而仔细对算法分析后可以发现,“拿来主义”在这里用不上了!

对算法的测试用例是p[3] = {25, 24, 15};w[3] = {18, 15, 10}。得到的结果如下:

please input the total count of object: 3

Please input array of p :

25 24 15

Now please input array of w :

18 15 10

sortResult[i] is :

1 -107374176.000000 1 1.600000 2 1.600000

after arithmetic data: x[i]

0.000000 0.333333 0.000000

可以看到其效益为x[3] = {1.4, 1.6, 1.5},于是在M = 20的情况下,其预想中的输出结果是0,1,0.5。然而事实上是不是就这样呢?

当程序进入此函数经过必要的变量初始化后,进入了外围循环,也就是程序的第7行。第一轮循环中,temp = tempArray[0] = 1.4,index = i = 0;程序运行到第15行,也就是进入了内层循环。

内层循环的主要任务是从第i + 1个元素之后找到一个最大的效益并保存此时的下标。到了第24行后,就开始对w[i]进行排序。

问题就在这里了!排序后的w[i] = {1.6, 1.6, 1.5},因此对w[i]排序后就既改变了w[i]的原有顺序,还改变了w[i]的原来值!

据此,做出一些修改,得到了如下的一段代码:

1 void sort(float tempArray[], int sortResult[], int n)

2 {

3 int i = 0, j = 0;

4 int index = 0, k = 0;

5

6 for (i = 0; i

7 {

8 sortResult[i] = 0;

9 }

10

11 for (i = 0; i

12 {

13 float swapMemory = 0;

14 float temp;

15

16 temp = tempArray[i];

17 index = i;

18

19 for (j = i; j

20 {

21 if ((temp

23 temp = tempArray[j];

24 index = j;

25 }

26 }

27

28 if (sortResult[index] == 0)

29 {

30 sortResult[index] = ++k;

31 }

32 }

33

34 for (i = 0; i

35 {

36 if (sortResult[i] == 0)

37 {

38 sortResult[i] = ++k;

39 }

40 }

41

42 return;

43 }

修改后最大的一个改变是没有继续沿用直接对w[i]排序,而是用w[i]的一个映射数组sortResult[i]。sortResult[i]中元素值存放的是根据效益计算得w[i]的大小顺序!这样w[i]原有的值和位置都没有改变,从而使算法得以实现!

至于有没有更好的实现版本,还在探索中!

#include

#define MAXSIZE 100 //假设物体总数

#define M 20 //背包的载荷能力

//算法核心,贪心算法

void GREEDY(float w[], float x[], int sortResult[], int n)

{

float cu = M;

int i = 0;

int temp = 0;

for (i = 0; i

{

x[i] = 0;

}

for (i = 0; i

{

temp = sortResult[i];//得到取物体的顺序

if (w[temp] > cu)

{

break;

}

x[temp] = 1;//若合适则取出

cu -= w[temp];//将容量相应的改变

}

if (i

{

x[temp] = cu / w[temp];

}

return;

}

void sort(float tempArray[], int sortResult[], int n)

{

int i = 0, j = 0;

int index = 0, k = 0;

for (i = 0; i

{

sortResult[i] = 0;

}

for (i = 0; i

{

float temp = tempArray[i];

index = i;

//找到最大的效益并保存此时的下标

for (j = 0; j

{

if ((temp

temp = tempArray[j];

index = j;

}

}

//对w[i]作标记排序

if (sortResult[index] == 0)

{

sortResult[index] = ++k;

}

}

//修改效益最低的sortResult[i]标记

for (i = 0; i

{

if (sortResult[i] == 0)

{

sortResult[i] = ++k;

}

}

return;

}

//得到本算法的所有输入信息

void getData(float p[], float w[], int *n) {

int i = 0;

printf("please input the total count of object: "); scanf("%d", n);

printf("Please input array of p :\n");

for (i = 0; i

{

scanf("%f", &p[i]);

}

printf("Now please input array of w :\n"); for (i = 0; i

{

scanf("%f", &w[i]);

#include

#include

using namespace std;

struct good//表示物品的结构体

{

double p;//价值

double w;//重量

double r;//价值与重量的比

}a[2000];

double s,value,m;

int i,n;

bool bigger(good a,good b)

{

return a.r>b.r;

}

int main()

{

scanf("%d",&n);//物品个数

for (i=0;i

{

scanf("%lf%lf",&a[i].w,&a[i].p);

a[i].r=a[i].p/a[i].w;

}

sort(a,a+n,bigger);//调用sort排序函数,你大概不介意吧,按照价值与重量比排序贪心 scanf("%lf",&m);//读入包的容量m

s=0;//包内现存货品的重量

value=0;//包内现存货品总价值

for (i=0;i

{

value+=a[i].p;

s+=a[i].w;

}

printf("The total value in the bag is %.2lf.\n",value);//输出结果

return 0;

}

贪心法是一种改进了的分级处理方法。用贪心法设计算法的特点是一步一步地进行,根据某个优化测度(可能是目标函数,也可能不是目标函数),每一步上都要保证能获得局部最优解。每一步只考虑一个数据,它的选取应满足局部优化条件。若下一个数据与部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加为止。这种能够得到某种度量意义下的最优解的分级处理方法称为贪心法。

选择能产生问题最优解的最优度量标准是使用贪心法的核心问题。

假定有n个物体和一个背包,物体i 有质量wi,价值为pi,而背包的载荷能力为M。若将物体i的一部分xi(10,1

要想得到最优解,就要在效益增长和背包容量消耗两者之间寻找平衡。也就是说,总应该把那些单位效益最高的物体先放入背包。

在实现算法的程序中,实现算法的核心程序倒没碰到很大的问题,然而实现寻找最优度量标准程序时麻烦不断!

在寻找最优度量标准时,大致方向是用冒泡排序算法。也就是根据p[i]/w[i]的大小来对w[i]来排序。

在直接用此算法时,可以有如下的一段代码:

//根据效益tempArray[i]对重量w[i]排序,为进入贪心算法作准备

1 void sort(float tempArray[], flaot w[], int n)

2 {

3 int i = 0, j = 0;

4 int index = 0;

5

6 //用类似冒泡排序算法,根据效益p[i]/w[i]对w[i]排序

7 for (i = 0; i

8 {

9 float swapMemory = 0;

10 float temp;

11

12 temp = tempArray[i];

13 index = i;

14

15 for (j = i + 1; j

16 {

17 if (temp

18 {

19 temp = tempArray[j];

20 index = j;

21 }

22 }

23

24 //对w[i]排序

25 swapMemory = w[index];

26 w[index] = w[i];

27 w[i] = swapMemory;

28 }

29

30 return;

31 }

然而仔细对算法分析后可以发现,“拿来主义”在这里用不上了!

对算法的测试用例是p[3] = {25, 24, 15};w[3] = {18, 15, 10}。得到的结果如下:

please input the total count of object: 3

Please input array of p :

25 24 15

Now please input array of w :

18 15 10

sortResult[i] is :

1 -107374176.000000 1 1.600000 2 1.600000

after arithmetic data: x[i]

0.000000 0.333333 0.000000

可以看到其效益为x[3] = {1.4, 1.6, 1.5},于是在M = 20的情况下,其预想中的输出结果是0,1,0.5。然而事实上是不是就这样呢?

当程序进入此函数经过必要的变量初始化后,进入了外围循环,也就是程序的第7行。第一轮循环中,temp = tempArray[0] = 1.4,index = i = 0;程序运行到第15行,也就是进入了内层循环。

内层循环的主要任务是从第i + 1个元素之后找到一个最大的效益并保存此时的下标。到了第24行后,就开始对w[i]进行排序。

问题就在这里了!排序后的w[i] = {1.6, 1.6, 1.5},因此对w[i]排序后就既改变了w[i]的原有顺序,还改变了w[i]的原来值!

据此,做出一些修改,得到了如下的一段代码:

1 void sort(float tempArray[], int sortResult[], int n)

2 {

3 int i = 0, j = 0;

4 int index = 0, k = 0;

5

6 for (i = 0; i

7 {

8 sortResult[i] = 0;

9 }

10

11 for (i = 0; i

12 {

13 float swapMemory = 0;

14 float temp;

15

16 temp = tempArray[i];

17 index = i;

18

19 for (j = i; j

20 {

21 if ((temp

23 temp = tempArray[j];

24 index = j;

25 }

26 }

27

28 if (sortResult[index] == 0)

29 {

30 sortResult[index] = ++k;

31 }

32 }

33

34 for (i = 0; i

35 {

36 if (sortResult[i] == 0)

37 {

38 sortResult[i] = ++k;

39 }

40 }

41

42 return;

43 }

修改后最大的一个改变是没有继续沿用直接对w[i]排序,而是用w[i]的一个映射数组sortResult[i]。sortResult[i]中元素值存放的是根据效益计算得w[i]的大小顺序!这样w[i]原有的值和位置都没有改变,从而使算法得以实现!

至于有没有更好的实现版本,还在探索中!

#include

#define MAXSIZE 100 //假设物体总数

#define M 20 //背包的载荷能力

//算法核心,贪心算法

void GREEDY(float w[], float x[], int sortResult[], int n)

{

float cu = M;

int i = 0;

int temp = 0;

for (i = 0; i

{

x[i] = 0;

}

for (i = 0; i

{

temp = sortResult[i];//得到取物体的顺序

if (w[temp] > cu)

{

break;

}

x[temp] = 1;//若合适则取出

cu -= w[temp];//将容量相应的改变

}

if (i

{

x[temp] = cu / w[temp];

}

return;

}

void sort(float tempArray[], int sortResult[], int n)

{

int i = 0, j = 0;

int index = 0, k = 0;

for (i = 0; i

{

sortResult[i] = 0;

}

for (i = 0; i

{

float temp = tempArray[i];

index = i;

//找到最大的效益并保存此时的下标

for (j = 0; j

{

if ((temp

temp = tempArray[j];

index = j;

}

}

//对w[i]作标记排序

if (sortResult[index] == 0)

{

sortResult[index] = ++k;

}

}

//修改效益最低的sortResult[i]标记

for (i = 0; i

{

if (sortResult[i] == 0)

{

sortResult[i] = ++k;

}

}

return;

}

//得到本算法的所有输入信息

void getData(float p[], float w[], int *n) {

int i = 0;

printf("please input the total count of object: "); scanf("%d", n);

printf("Please input array of p :\n");

for (i = 0; i

{

scanf("%f", &p[i]);

}

printf("Now please input array of w :\n"); for (i = 0; i

{

scanf("%f", &w[i]);


相关文章

  • 贪心算法的应用
  • 贪心算法的应用 课程名称: 院 系: 学生姓名: 学 号: 专业班级: 指导教师: 201312-27 贪心算法的应用 摘 要:顾名思义,贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义 ...查看


  • 基于贪心算法的0_1背包问题
  • ISSN1009-3044第6卷第35期(2010年12月)与技术ComputerKnowledgeandTechnology电脑知识 Vol.6,No.35,December2010,pp.10061-10062E-mail:xsjl@c ...查看


  • 算法设计与分析论文
  • 贪心算法 --不在贪心中爆发,就在贪心中灭亡 武汉理工大学计算机科学与技术学院班 摘要 本文介绍贪心算法的基本意义以及算法的使用范围,并通过具体的案例来分析贪心算法的具体应用,从而指出其特点和存在问题. 关键字:贪心算法,贪心策略,TSP. ...查看


  • 贪心算法思想
  • 贪心算法思想 顾名思义,贪心算法总是作出在当前看来最好的选择.也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择.当然,希望贪心算法得到的最终结果也是整体最优的.虽然贪心算法不能对所有问题都得到整体最优解,但对 ...查看


  • 算法设计与分析复习题目及答案
  • 分治法 1.二分搜索算法是利用( 分治策略)实现的算法. 9. 实现循环赛日程表利用的算法是(分治策略 ) 27.Strassen矩阵乘法是利用(分治策略 )实现的算法. 34.实现合并排序利用的算法是(分治策略 ). 实现大整数的乘法是利 ...查看


  • 贪心算法 实验二报告
  • 实验二 贪心选择算法 姓名 : 田圆圆 学号:2013125135 一.实验目的与要求: 理解贪心选择算法的思想. 二.预习与准备:贪心选择算法思想: (1)贪心选择能得到问题的最优解,要证明我们所做的第一步选择一定包含在一个最优解总,即存 ...查看


  • 背包问题贪心算法解决
  • 贪心算法求解背包问题 一. 实验内容 有一个承重为W的背包和n个物品,它们各自的重量和价值分别是wi和vin Wwi求这些物品中最有价值的一个子集.如果每次选择某(1 i1一个物品的时候,只能全部拿走,则这一问题称为离散(0-1)背包 ...查看


  • 贪心算法背包问题 1
  • 算法设计与分析实验报告 题目:贪心算法 背包问题 专业:JAVA技术09--02班 学号:[1**********]1 姓名:柏顺顺 指导老师:宋胜利 实验三:贪心算法 背包问题 一.实验目的与要求 1.掌握背包问题的算法 2.初步掌握贪心 ...查看


  • 2013计算机算法设计与分析期终考试复习题
  • 计算机算法设计与分析复习题 一.填空题 1.一个算法复杂性的高低体现在计算机运行该算法所需的时间和存储器资源上,因此算法的复杂性有 时间 复杂性和空间复杂性之分. 2.出自于"平衡子问题"的思想,通常分治法在分割原问题, ...查看


热门内容