贪心法 背包问题副本.docx

上传人:b****9 文档编号:25845730 上传时间:2023-06-16 格式:DOCX 页数:32 大小:191.18KB
下载 相关 举报
贪心法 背包问题副本.docx_第1页
第1页 / 共32页
贪心法 背包问题副本.docx_第2页
第2页 / 共32页
贪心法 背包问题副本.docx_第3页
第3页 / 共32页
贪心法 背包问题副本.docx_第4页
第4页 / 共32页
贪心法 背包问题副本.docx_第5页
第5页 / 共32页
点击查看更多>>
下载资源
资源描述

贪心法 背包问题副本.docx

《贪心法 背包问题副本.docx》由会员分享,可在线阅读,更多相关《贪心法 背包问题副本.docx(32页珍藏版)》请在冰豆网上搜索。

贪心法 背包问题副本.docx

贪心法背包问题副本

课程设计(论文)

题目

贪心法:

背包问题

姓名

学号

指导老师

指导教师职称

教授

年级专业班级

所在学院

理学院

2014年4月25日

目录

目录1

摘要2

前言3

1课题背景4

1.1背景4

1.2需求分析5

1.3贪心法介绍以及注意事项…………………………………………………..…5

1.4意义6

1.5文献综述…………………………………………………………………..…….6

2设计简介及设计方案论述7

2.1设计简介7

2.2设计方案论述7

3详细设计………………..…………………………………………….………......8

3.1物品的存储和链队结点的定义8

3.2物品链队结点全局头指针的定义8

3.3物品链队的入队和出对操作……………..……….......................................9

3.4菜单的设计………..…………………………………………………………….9

4设计结果及分析16

4.1测试结果18

4.2问题解决………..……………………………………………………………..18

5总结20

致谢22

参考文献23

附录程序代码24

摘要

本课题主要是运用VC6.0,开发基于控制台下的贪心法背包问题的选择程序。

本文较详细地介绍了这一程序的设计思想,功能结构以及队列的设计和某些功能函数的设计。

本文还给出了对这一程序的测试情况以及对测试结果的分析。

关键词:

GoodsEnQueue,GoodsDeQueue,head,算法与数据结构

前言

本文详细介绍了贪心法背包问题的设计与开发。

全文共5章。

第1章介绍了贪心法背包问题的背景,以及它所要实现的基本功能。

并根据这些用户需求,进行了必要的需求分析,从而确定了该程序应实现了一些基本功能。

本章中,还简要地介绍了该程序开发的意义以及在整个开发过程中,我们所查阅并借用的一些参考文献的主要内容。

第2章主要介绍了贪心法背包问题程序中各功能模块的总体框图,主要链队的设计以及各链队之间的相互关系,这是全文的核心部分。

第3章是贪心法背包问题程序的详细设计,我们给出了主要链队的设计,关于链队的入队和出队问题,并给出了其程序。

第4章是对所开发的背包问题程序的运行测试。

通过我们所设计的部分测试数据,检验程序是否达到了预定的设计要求。

第5章是对关于运用贪心法解决背包问题程序开发过程的总结。

总结了本次课程设计的意义,以及测试中所发现的一些问题,有待进一步改进的地方。

重点还谈到了我在本次课程设计中的收获与感想。

全文的最后是致谢、参考文献和程序的全部源代码。

XX

2014-4-25于武汉工程大学理学院

课题背景

2.1背景

有一容量为200(米3)的背包,8种物品的编号、体积和价值如下表所示。

现要将物品装进背包,要求不能超过背包的容量且物品总价值最大,该如何装包?

编号

体积(单位:

米3)

价值(单位:

元)

1

40

35

2

55

20

3

20

20

4

65

40

5

30

35

6

40

15

7

45

40

8

35

20

很容易想到3种贪心策略:

1每次取价值最大的物品;

2每次取体积最小的物品;

3每次取单位体积价值最大的物品。

2.2需求分析

根据上面给出的问题,我们可以运用贪心法和链队操作来解决。

而且,我们必须通过程序来实现上面背包问题的3种贪心策略,并与之做出比较,选出最好的策略。

2.3贪心法介绍及注意事项

(1)多阶段决策问题、无后向性与最优化原理

多阶段决策问题是指这样一类问题:

问题的解决过程可以分为若干阶段,在每一阶段都做出相应的决策,所有决策构成的决策序列就是问题的解决方案。

多阶段决策问题有一个共同特点:

每一阶段面临的问题都是原问题的一个子问题,而且子问题的解决只与当前阶段和以后阶段的决策有关,与以前各阶段的决策无关。

我们称这类问题具有无后向性的特点。

所谓最优化原理,是说一个问题的最优策略有这样的一个性质,不论以前的决策如何,对于当前的子问题,其余的决策一定构成最优策略。

最优化原理可以简单地描述为:

一个最优策略的子策略总是最优的。

一个问题满足最优化原理,又称它为具有最优子结构性质。

例如,4个城市A、B、C、D间的道路如下图所示:

如果A到D的最短路线为A→B→D,那么B到D的最短路线为B→D。

可以用反证法证明:

如果B到D的最短路线不是B→D,假设另一条路径B=>D更短,那么A→B=>D就比A→B→D更短,与题设矛盾。

所以B→D是B到D的最短路线。

在解决背包问题时,运用了这样的一种策略,就是在求最优解过程的每一步都采用一种局部最优的策略,即优先考虑将价值密度大的物品放入背包,把问题的范围和规模缩小,最后把每一步的结果合并起来得到一个最优解。

归纳起来,运用贪心法解题的一般步骤是:

1从问题的某个初始解出发。

2采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。

3将所有部分解综合起来,得到问题的最优解。

(2)用贪心法解题的注意事项

一个多阶段决策问题如果满足最优化原理,就可以考虑使用贪心法来解。

如果这个条件不是那么明显,在解题前应该先进行证明,有时可能还要对原题进行一些转化才行。

要注意的是,一个问题具有无后向性特点,不一定就满足最优化原理。

而一个问题满足最优化原理,也不一定就能用贪心法求解。

例如,某国家的货币体系包含n种面值(其中一定有面值为1的),现有一种商品价格为p,请问最少用多少枚货币可以正好买下?

该问题满足最优化原理。

如果试图用贪心法来解,一个很容易想到的贪心策略是:

尽量用面值大的的货币。

这个策略在很多情况下是有效的。

例如我国的货币体系为{1,2,5,10,20,50,100}。

又如美国的货币体系为{1,5,10,25,100}。

这一策略总能得到最优解。

但如果某国家的货币体系为{1,5,8,10},p=13,则这一贪心策略得到的结果是4枚货币,而值分别为10、1、1、1,而最优策略是2枚货币,面值为8和5。

贪心法失效了。

很可惜,目前并没有一个一般性的结论,可以保证贪心法一定得到问题的最优解。

因此,在应用贪心法之前,应该先论证当前的策略能否得到问题的最优解。

对于上面的货币问题,贪心法并不能保证得到最优解。

一般需用动态规划方法来解决。

有些问题能应用贪心法来解,但需要选择适当的局部最优策略,才能得到正确结果。

1.4意义

关于贪心法的相关知识,是我们信息与计算科学专业必须了解的经典算法之一。

它在程序中的作用肯定是毋庸置疑,对于我们以后的工作有时也有着指导作用。

采用C++算法与数据结购的思想,设计与开发背包问题的算法程序,有助于我们了解对该门课程的掌握程度及自身的运用学习能力。

2.4文献综述

文献[1]较详细地介绍了贪心法背包问题程序的设计与开发以及C++的一些基本知识,它对于我们了解C++知识,运用C++进行算法与数据结构有非常直接的帮助。

文献[2]介绍了C++程序设计的主要思想与方法,在解决贪心法背包问题程序时,我们参考该书中许多技巧以及接口程序的设计,链队的操作等。

设计简介及设计方案论述

2.5设计简介

根据需求分析,我们将设计三个策略程序:

1每次取价值最大的物品;

2每次取体积最小的物品;

3每次取单位体积价值最大的物品。

其物品链队操作结构见图2-1,其功能结构见其图2-2。

GoodsEnqueue(含参数)

GoodsDequeue(含参数)

Goods2Enqueue(含参数)

GoodsDequeue(含参数)

Goods3Enqueue(含参数)

GoodsDequeue(含参数)

图2-1入队和出队的结构

背包问题系统:

背包问题贪心策略

1每次取价值最大的物品

2每次取体积最小的物品

3每次取单位体积价值最大的物品

4退出程序

图2-2系统的功能结构

2.6设计方案论述

背包问题中的物品用数组进行存储,然后通过链队的入队操作进行简单的升序或降序排列,再通过出队操作去进行其他程序操作。

在主函数中通过switch函数做出3种贪心策略的选择操作,并实现其功能。

详细设计

2.7物品的存储和链队结点的定义

DoubleGoods[N][3]={{1,40,35},{2,55,20},{3,20,20},{4,65,40},{5,30,35},{6,40,15},{7,45,40},{8,35,20}};

structNode//链队结点

{

doublenum;//物品编号

doublevolume;//物品体积

doublevalue;//物品价值

doublev;//单位体积价值

structNode*next;

};

2.8物品链队结点全局头指针的定义

//定义物品链队全局头指针

Node*head=NULL;

2.9物品链队的入队和出对操作

//物品依价值按升序入链队

voidGoodsEnQueue(doublenum,doublevolume,doublevalue)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=volume;

newnode->value=value;

newnode->next=NULL;

//入链队

if(head==NULL)//空链队

head=newnode;

else//非空链队

{//寻找链尾结点

p=head;

while(p->next!

=NULL)

p=p->next;

rear=p;

if(newnode->valuevalue)//插链头

{newnode->next=head;

head=newnode;

}

elseif(newnode->value>=rear->value)//插链尾

rear->next=newnode;

else

{//插中间

p=head;

while(newnode->value>=p->value)

{q=p;

p=p->next;

}

newnode->next=q->next;

q->next=newnode;

}

}

}

//物品依体积按降序序入链队

voidGoods2EnQueue(doublenum,doublevolume,doublevalue)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=volume;

newnode->value=value;

newnode->next=NULL;

//入链队

if(head==NULL)//空链队

head=newnode;

else//非空链队

{//寻找链尾结点

p=head;

while(p->next!

=NULL)

p=p->next;

rear=p;

if(newnode->volume>head->volume)//插链头

{newnode->next=head;

head=newnode;

}

elseif(newnode->volume<=rear->volume)//插链尾

rear->next=newnode;

else

{//插中间

p=head;

while(newnode->volume<=p->volume)

{q=p;

p=p->next;

}

newnode->next=q->next;

q->next=newnode;

}

}

}

//物品依单位体积按降序序入链队

voidGoods3EnQueue(doublenum,doublevolume,doublevalue,doublev)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=volume;

newnode->value=value;

newnode->v=v;

newnode->next=NULL;

//入链队

if(head==NULL)//空链队

head=newnode;

else//非空链队

{//寻找链尾结点

p=head;

while(p->next!

=NULL)

p=p->next;

rear=p;

if(newnode->v>head->v)//插链头

{newnode->next=head;

head=newnode;

}

elseif(newnode->v<=rear->v)//插链尾

rear->next=newnode;

else

{//插中间

p=head;

while(newnode->v<=p->v)

{q=p;

p=p->next;

}

newnode->next=q->next;

q->next=newnode;

}

}

}

voidGoodsDeQueue(double&num,double&volume,double&value)

{Node*p;//探测指针

if(IsEmpty(head))//如果链队为空

{cout<<"物品链队空,无法出队!

"<

return;

}

elseif(head->next==NULL)//链队仅有惟一结点

{p=head;

num=p->num;

volume=p->volume;

value=p->value;

head=NULL;//将链队置空

deletep;//删除链队头结点

}

else//链队具有两个以上结点

{p=head;

num=p->num;

volume=p->volume;

value=p->value;

head=head->next;//链队头指针指向下一个结点

deletep;//删除链队头结点

}

}

3.4菜单的设计

voidMenu()

{

cout<<"________________________"<

cout<<"背包问题贪心策略"<

cout<<"\n1每次取价值最大的物品"<

cout<<"\n2每次取体积最小的物品"<

cout<<"\n3每次取单位体积价值最大的物品"<

cout<<"\n4退出程序"<

cout<<"________________________"<

cout<<"请输入相对有的数字:

"<

}

设计结果及分析

2.10测试结果

图4-1-1程序运行后显示的菜单

图4-1-2策略1的输出结果

图4-1-3策略2的输出结果

图4-1-4策略3的输出结果

通过图形比较,我们能够知道第3种贪心策略是最好的。

2.11问题解决

通过菜单函数不能连续按数字实现程序功能?

解决办法:

在主函数中初始化GoodsValue=0,GoodsVolume=0不能放在do循环之外,而应放在其里面。

总结

贪心法在求解过程的每一步都采取局部最优策略,使问题的规模一步步缩小,期望每一步的局部最优达到最后总体上的全局最优。

但是有时局部最优并不能保证全局最优,这是采用贪心法时要注意的地方;最优化原理可简述为:

一个最优策略的子策略总是最优的;一个多阶段决策问题如果满足最优化原理,则可考虑用贪心法求解,否则须先行证明而后采用,或者要对原题进行某种转化才可使用,也可能根本就不可用,这要看是否满足最优化原理。

这次课程设计,是我与同学一起第一次合作完成较大的程序编写,开始时,我们心里根本没底,想都不敢想自已能写出一点东西来,并真正地解决这一实际问题。

但随着工作的逐渐深入,对问题的理解越来越透彻,想写的东西越来越多,信心越来越足,程序越编越大,系统的功能越做越强。

当我们洋洋洒洒地撰写完千余行代码,将一个又一个功能模块实现出来,并将它们调试通过之后,那种喜悦感、幸福感、成就感让我感到兴奋。

我终于等到了所谓“开窍”的这一刻,原来它是这样的一种感觉。

此时此刻,回想一年来学习编程的经历,我明白了这样一个道理:

此时的喜悦感、幸福感、成就感,不正好是过去的沮丧、痛苦、自卑所带来的馈赠吗!

其实,这种道理对我们这个年龄段的青年人,谁人不知又谁人不晓呢,它所应证的不就是那几句老名言吗?

不经历风雨,怎么能见彩虹

宝剑锋从磨砺出,梅花香自苦寒来

让我们值得进一步思考的是,为什么我们一碰到困难,就忘记了这些至理名言呢?

为什么我们一遇到挫折,总希望别人来安慰与鼓励,甚至是扶你前行呢?

通过学习算法与数据结构,我们了解到电脑上的许多东西都可以用算法来进行实现。

在老师的严格教导下,我们从中收获颇多。

像什么单链表操作及队列操作的学习和编程,对于它们,我们已经有了一定的了解。

以后的学习,我们应更加刻苦钻研。

平时学习不够扎实,没有刻苦的钻研,就会导致我们这次的诸多不顺。

这次的苦果是我们咎由自取,我想我们应该要更加学习了,虽然说出来比较容易,但真的要学习了。

没有一个人会喜欢自己做得很差,相反地,任何人都希望做得最好。

不过,在我的词典里,没有最好,只有更好。

伟大的科学家爱因斯坦说过,成功等于99%的努力加1%的灵感。

在得到这些荣誉的前提下,我们必须付出珍贵的时间和辛勤的汗水。

致谢

一份课程设计的总结,一份对老师的感谢。

虽然我们课程设计程序代码在这学期开始的时候已经有了,但是在明天即将给老师的时刻,程序代码也发生了许多变化,功能也逐渐提高;一些变化,一些收获。

老师说过:

“道虽远,不行不至;事虽难,不为不成。

”这专业真的很累,老师们累,学生们也累,谢谢老师们和我们一起坚持着。

明天结果如何是无法知道的,而今天我们都努力过。

参考文献

[1]《C++程序设计》(第二版),谭浩强著,清华大学出版社

[2]《程序设计基础》(第三版),吴文虎徐明星编著,清华大学出版社

附录程序代码

#include

usingnamespacestd;

#defineM200//背包体积容量为200

#defineN8//物品序号

doubleGoods[N][3]={{1,40,35},{2,55,20},{3,20,20},{4,65,40},{5,30,35},{6,40,15},{7,45,40},{8,35,20}};

structNode//链队结点

{

doublenum;//物品编号

doublevolume;//物品体积

doublevalue;//物品价值

doublev;//单位体积价值

structNode*next;

};

//定义物品链队全局头指针

Node*head=NULL;

//判空

intIsEmpty(Node*head)

{

if(head==NULL)

return1;

else

return0;

}

//物品依价值按升序入链队

voidGoodsEnQueue(doublenum,doublevolume,doublevalue)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=volume;

newnode->value=value;

newnode->next=NULL;

//入链队

if(head==NULL)//空链队

head=newnode;

else//非空链队

{//寻找链尾结点

p=head;

while(p->next!

=NULL)

p=p->next;

rear=p;

if(newnode->valuevalue)//插链头

{newnode->next=head;

head=newnode;

}

elseif(newnode->value>=rear->value)//插链尾

rear->next=newnode;

else

{//插中间

p=head;

while(newnode->value>=p->value)

{q=p;

p=p->next;

}

newnode->next=q->next;

q->next=newnode;

}

}

}

//物品依体积按降序序入链队

voidGoods2EnQueue(doublenum,doublevolume,doublevalue)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=volume;

newnode->value=value;

newnode->next=NULL;

//入链队

if(head==NULL)//空链队

head=newnode;

else//非空链队

{//寻找链尾结点

p=head;

while(p->next!

=NULL)

p=p->next;

rear=p;

if(newnode->volume>head->volume)//插链头

{newnode->next=head;

head=newnode;

}

elseif(newnode->volume<=rear->volume)//插链尾

rear->next=newnode;

else

{//插中间

p=head;

while(newnode->volume<=p->volume)

{q=p;

p=p->next;

}

newnode->next=q->next;

q->next=newnode;

}

}

}

//物品依单位体积按降序序入链队

voidGoods3EnQueue(doublenum,doublevolume,doublevalue,doublev)

{Node*p,*q,*rear,*newnode;

//生成新结点

newnode=newNode;

newnode->num=num;

newnode->volume=vo

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 唐诗宋词

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1