贪心算法实验
贪心算法实验(求解背包问题)

算法分析与设计实验报告第四次实验
}
}
输入较小的结果:
测试结
果
输入较大的结果:
附录:
完整代码(贪心法)
;
cout<<endl;
cout<<"待装物品的价值为:"<<endl;
for (i=0;i<n;i++)
cin>>item[i].v;
cout<<endl;
erval=item[i].v/item[i].w;
clock_t start,end,over; ;
实验心
得
首先这个实验,需要注意的点是背包问题与0-1背包不同,物品可以部分的放入背包中,所以思路也不一样,首先就是将物品按照单位质量价值排序,只这一点就有一点难度。
难度在于要是排序后物品的编号就会发生改变,输出的就不是之前的编号的物品,导致错误,后来发现如果为每一个物品保存一个副本,然后将它们的编号进行对比,就可以进行正确的输出了。
其中这个实验
让我学到了两点:一是结构体的使用,之前一直没有怎么用过,现在才发现自己其实不会用;二十对于库函数sort 函数的使用。
感觉每一次实验都有学到东西,很开心。
实验得
分 助教签名
sort(item,item+n,comparison); >c)
break;
tem[i]=1;
c-=item[i].w;
}
if(i<n) ;
for(i=0;i<n;i++) ==tmp[j])
x[j]=tem[i];
}
}
}。
c++贪心算法经典例题

c++贪心算法经典例题
经典的贪心算法例题有很多,以下是其中几个常见的例题:
1. 分糖果问题:
有一群小朋友,每个人都有一个评分。
现在需要给他们分糖果,要求评分高的小朋友比他旁边评分低的小朋友拥有更多的糖果。
求至少需要准备多少糖果。
2. 区间覆盖问题:
给定一个区间集合,每个区间表示一个工作时间段。
现在需要选择尽可能少的区间,覆盖整个时间范围。
求最少需要选择多少个区间。
3. 最佳买卖股票时机:
给定一个股票的价格列表,可以任意次数买入和卖出股票。
但是同一时间只能持有一支股票,求能够获得的最大利润。
4. 最大会议安排:
给定一系列的会议,每个会议有开始时间和结束时间。
要求安排尽可能多的会议,使得它们不会发生时间上的冲突。
5. 跳跃游戏:
给定一个非负整数数组,每个元素表示在该位置上能够跳跃的最大长度。
初始位置在第一个元素,判断能否跳到最后一个元素。
以上仅是一些常见的例题,贪心算法广泛应用于各种问题中。
在解决实际问题时,需要根据具体情况设计贪心策略,找到合适的贪心策略才能得到正确的解答。
贪心算法实验报告心得

贪心算法实验报告心得前言贪心算法是一种常见且重要的算法设计思想,通过每一步都选择当下最优的解决方案,以期望最终得到全局最优解。
在学习与实践贪心算法的过程中,我有了许多心得与体会。
什么是贪心算法?贪心算法是一种求解问题的算法思想,它的特点是每一步都选择当前最优的解决方案,而不考虑该选择对以后步骤的影响。
贪心算法通常适用于可以将问题分解为若干个子问题,并且通过每次选择当前最优解来得到整体最优解的情况。
贪心算法的基本步骤贪心算法的基本步骤可以总结为以下几个方面:1.确定问题的解空间,并找到问题的最优解。
贪心算法通常通过穷举法或者利用问题的特殊性质来确定解空间。
2.制定贪心策略。
贪心算法的核心是确定每一步选择的贪心策略,即选择当前最优解。
3.确定贪心策略的正确性。
贪心算法的一个关键问题是如何证明贪心策略的正确性。
可以通过数学证明、反证法或者举反例等方式来进行证明。
4.实现贪心算法。
将贪心策略转化为实际可执行的算法步骤,编写代码来求解问题。
贪心算法实验结果分析在本次实验中,我使用贪心算法解决了一个经典问题:找零钱问题(Change-Making Problem)。
给定一定面额的硬币和需找的金额,我们的目标是使用最少的硬币来完成找零钱。
贪心算法的思路是每次选择面额最大的硬币进行找零。
实验设计1.实验输入:我设计了多组输入来测试贪心算法的性能。
每组输入包括一个需找的金额和一个硬币集合。
2.实验输出:对于每组输入,贪心算法输出一个最优的硬币找零方案,以及使用的硬币数量。
3.实验评价:我使用了实际需找金额与贪心算法计算得到的找零金额的差值来评估算法的准确性,并统计了算法的时间复杂度。
实验结果从多组实验结果中可以观察到,贪心算法在大部分情况下给出了正确的找零金额,并且算法的时间复杂度较低。
结果分析贪心算法在找零钱问题中的应用是合理的。
每次选择面额最大的硬币进行找零,可以快速接近最优解,并且相对其他算法具有较低的时间复杂度。
贪心算法几个经典例子c语言

贪心算法几个经典例子c语言1. 零钱兑换问题题目描述:给定一些面额不同的硬币和一个总金额,编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
如果没有任何一种硬币组合能够凑出总金额,返回 -1。
贪心策略:每次选择面额最大的硬币,直到凑出总金额或者无法再选择硬币为止。
C语言代码:int coinChange(int* coins, int coinsSize, int amount){int count = 0;for(int i = coinsSize - 1; i >= 0; i--){while(amount >= coins[i]){amount -= coins[i];count++;}}return amount == 0 ? count : -1;}2. 活动选择问题题目描述:有 n 个活动,每个活动都有一个开始时间和结束时间,选择一些活动使得它们不冲突,且能够参加的活动数最多。
贪心策略:每次选择结束时间最早的活动,直到所有活动都被选择或者无法再选择为止。
C语言代码:typedef struct{int start;int end;}Activity;int cmp(const void* a, const void* b){return ((Activity*)a)->end - ((Activity*)b)->end;}int maxActivities(Activity* activities, int n){qsort(activities, n, sizeof(Activity), cmp);int count = 1;int end = activities[0].end;for(int i = 1; i < n; i++){if(activities[i].start >= end){count++;end = activities[i].end;}}return count;}3. 跳跃游戏题目描述:给定一个非负整数数组,你最初位于数组的第一个位置。
贪心算法-找零问题 实验报告

实验三课程名称:算法设计与实现实验名称:贪心算法-找零问题实验日期:2019年5月2日仪器编号:007班级:数媒0000班姓名:郝仁学号0000000000实验内容假设零钱系统的币值是{1,p,p^2,……,p^n},p>1,且每个钱币的重量都等于1,设计一个最坏情况下时间复杂度最低的算法,使得对任何钱数y,该算法得到的零钱个数最少,说明算法的主要设计思想,证明它的正确性,并给出最坏情况下的时间复杂度。
实验分析引理1(离散数学其及应用3.1.4):若n是正整数,则用25美分、10美分、5美分和1美分等尽可能少的硬币找出的n美分零钱中,至多有2个10美分、至多有1个5美分、至多有4个1美分硬币,而不能有2个10美分和1个5美分硬币。
用10美分、5美分和1美分硬币找出的零钱不能超过24美分。
证明如果有超过规定数目的各种类型的硬币,就可以用等值的数目更少的硬币来替换。
注意,如果有3个10美分硬币,就可以换成1个25美分和1个5美分硬币;如果有2个5美分硬币,就可以换成1个10美分硬币;如果有5个1美分硬币,就可以换成1个5美分硬币;如果有2个10美分和1个5美分硬币,就可以换成1个25美分硬币。
由于至多可以有2个10美分、1个5美分和4个1美分硬币,而不能有2个10美分和1个5美分硬币,所以当用尽可能少的硬币找n美分零钱时,24美分就是用10美分、5美分和1美分硬币能找出的最大值。
假设存在正整数n,使得有办法将25美分、10美分、5美分和1美分硬币用少于贪心算法所求出的硬币去找n美分零钱。
首先注意,在这种找n美分零钱的最优方式中使用25美分硬币的个数q′,一定等于贪心算法所用25美分硬币的个数。
为说明这一点,注意贪心算法使用尽可能多的25美分硬币,所以q′≤q。
但是q′也不能小于q。
假如q′小于q,需要在这种最优方式中用10美分、5美分和1美分硬币至少找出25美分零钱。
而根据引理1,这是不可能的。
板材切割优化算法的实现与比较

板材切割优化算法的实现与比较第一章引言板材切割是制造业中重要的工艺之一,目的是最大限度地利用板材,减少浪费。
随着计算机技术的不断发展,利用计算机实现板材切割优化算法已成为当前工业界广泛关注的研究领域之一。
板材切割的优化算法旨在找到一种最优的切割方案,以最小化废料数量或最大化使用率。
本文将介绍两种常见的板材切割优化算法,分别是贪心算法和遗传算法,通过实验比较两种算法的性能,并着重讨论如何在实际应用中选择最佳的算法。
第二章贪心算法贪心算法是一种简单的启发式算法。
它的主要思想是在每一步中选择当前最好的选择,以期望最终结果也是最佳的。
在板材切割问题中,贪心算法的具体实现如下:1.按照板材尺寸排序,从最大的板材开始切割。
2.选择合适的模板尺寸,以覆盖需要切割的板材。
3.尽可能多地剪出这一模板所能承载的片材数量。
4.重复步骤2和3,直至所有板材都被切割完毕。
尽管贪心算法非常简单易懂,但是在实际应用中,它并不总是最优的。
由于贪心算法只考虑当前的最优解,而忽视了全局最优解,因此在处理一些复杂的切割情况时可能出现不好的结果。
第三章遗传算法遗传算法是一种进化算法,其核心思想是通过模拟自然选择和遗传的过程,寻找最优解。
在板材切割问题中,遗传算法的具体实现如下:1.初始种群的生成:随机生成一组合法的切割方案,作为初始种群。
2.适应度函数的确定:以废料数量或使用率作为适应度函数。
3.选择:按照适应度函数的大小,选择某些个体作为下一代的父母。
4.交叉:通过随机选择两个父母来生成子代,交叉的位置也是随机的。
5.变异:通过随机的方式来改变个体的某个优化参数。
6.新种群的生成:将交叉和变异产生的子代和父代合并生成新的种群。
7.重复步骤3至6,直到达到终止条件。
可以看出,遗传算法能够全面考虑切割问题的多种变量和约束条件,因此,它通常比贪心算法更加优秀。
但是,由于遗传算法的实现非常复杂,计算量较大,因此速度相对较慢,不适合处理实时性要求比较高的切割场景。
算法分析与设计实验三贪心算法

实验三贪心算法实验目的1. 掌握贪心法的基本思想方法;2. 了解适用于用贪心法求解的问题类型,并能设计相应贪心法算法;3. 掌握贪心算法复杂性分析方法分析问题复杂性。
预习与实验要求1. 预习实验指导书及教材的有关内容,掌握贪心法的基本思想;2. 严格按照实验内容进行实验,培养良好的算法设计和编程的习惯;3. 认真听讲,服从安排,独立思考并完成实验。
实验设备与器材硬件:PC机软件:C++或Java等编程环境实验原理有一类问题是要从所有的允许解中求出最优解,其策略之一是“贪心法”,即逐次实施“贪心选择”:在每个选择步骤上做出的选择都是当前状态下最优的。
贪心选择依赖于在此之前所做出的选择,但不依赖于后续步骤所需要的选择,即不依赖于后续待求解子问题。
显然,这种选择方法是局部最优的,但不是从问题求解的整体考虑进行选择,因此不能保证最后所得一定是最优解。
贪心法是求解问题的一种有效方法,所得到的结果如果不是最优的,通常也是近似最优的。
实验内容以下几个问题选做一项:1. 用贪心法实现带有期限作业排序的快速算法应用贪心设计策略来解决操作系统中单机、无资源约束且每个作业可在等量时间内完成的作业调度问题。
假定只能在一台机器上处理N个作业,每个作业均可在单位时间内完成;又假定每个作业i都有一个截止期限di>0(它是整数),当且仅当作业i在它的期限截止以前被完成时,则获得pi的效益。
这个问题的一个可行解是这N个作业的一个子集合J,J中的每个作业都能在各自的截止期限之前完成。
可行解的效益值是J中这些作业的效益之和,即Σp。
具有最大效益值的可行解就是最优解。
2. 实现K元归并树贪心算法两个分别包含n个和m个记录的已分类文件可以在O(n+m)时间内归并在一起而得到一个分类文件。
当要把两个以上的已分类文件归并在一起时,可以通过成对地重复归并已分类的文件来完成。
例如:假定X1,X2,X3,X4是要归并的文件,则可以首先把X1和X2归并成文件Y1,然后将Y1和X3归并成Y2,最后将Y2和X4归并,从而得到想要的分类文件;也可以先把X1和X2归并成Y1,然后将X3和X4归并成Y2,最后归并Y1和Y2而得到想要的分类文件。
贪心算法_实验报告

贪心算法_实验报告一、设计分析●问题描述:键盘输入一个高精度的正整数N(N不超过240位),去掉其中任意S个数字后剩下的数字按原左右次序将组成一个新的正整数。
编程对给定的N和S,寻找一种方案使得剩下的数字组成的新数最小。
●设计思路:在位数固定的前提下,让高位的数字尽量小其值就较小,依据此贪心策略解决此问题。
删除高位较大的数字。
具体:相邻两位比较若高位比低位大则删除高位。
删除字符的方法:1)物理删除,用后面的字符覆盖已删除的字符。
有比较多字符移动操作,算法效率不高。
2)用数组记录字符的状态,“1”表示对应数字存在,“0”表示对应数字已删除。
3)利用数组,记录未删除字符的下标:n=“1 2 4 3 5 8 3 3”0 0 0 0 0 04比3大删除“1 2 3 5 8 3 3” 1 2 4 5 0 08比3大删除“1 2 3 5 3 3” 1 2 4 5 05比3大删除“1 2 3 3 3” 1 2 4 7 8二、程序代码c语言实现#include<stdio.h>#include<string.h>#define N 10000int main(void){char a[N];int i,j,k,n;printf("输入要处理的数据:\n");gets(a);printf("输入要删除的数字个数:\n");scanf("%d",&n);三、测试用例四、实验总结加深了对贪心算法的理解与运用。
所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中南大学《算法设计与分析》实验报告姓名:专业班级:学号:指导教师:完成日期:20010.1一.实验名称贪心算法实验二.实验目的1. 了解贪心算法思想2. 掌握贪心法典型问题,如背包问题、作业调度问题等。
三.实验内容1. 编写一个简单的程序,实现单源最短路径问题2. 编写一段程序,实现找零3. 编写程序实现多机调度问题四.算法思想分析1.单源最短路径问题(1)问题描述已知图G=(V,E),我们希望找出从某给定的源结点S∈V到V中的每个结点的最短路径。
首先,我们可以发现有这样一个事实:如果P是G中从vs到vj 的最短路,vi是P中的一个点,那么,从vs沿P到vi的路是从vs到vi的最短路。
(2)算法分析Dijkstra算法:算法的基本思想是从vs出发,逐步地向外探寻最短路。
执行过程中,与每个点对应,记录下一个数(称为这个点的标号),它或者表示从vs 到该点的最短路的权(称为P标号)、或者是从vs到该点的最短路的权的上界(称为T标号),方法的每一步是去修改T标号,并且把某一个具T标号的改变为具 P标号的点,从而使G中具P标号的顶点数多一个,这样至多经过n-1(n为图G的顶点数)步,就可以求出从vs到各点的最短路。
2.找零问题(1)问题描述当前有面值分别为2角5分,1角,5分,1分的硬币,请给出找n分钱的最佳方案(要求找出的硬币数目最少)(2)问题分析计算法实现根据常识,我们到店里买东西找钱时,老板总是先给我们最大面值的,要是不够再找面值小一点的,直到找满为止。
如果老板都给你找分数的或者几角的,那你肯定不干,另外,他也可能没有那么多零碎的钱给你找。
其实这就是一个典型的贪心选择问题。
假如要找77分钱,有上面的面值分别为25,10,5,1的硬币数,为了找最少的硬币数,那么他是不是该这样找呢,先看该找多少个25分的, 57/25=2,好像是2个,要是3个的话,我们还得再给老板一个1分的,这样不行,那么只能给2个25分的,由于还少给27,所以还得给我2个10分的,1个5分的和2个1分。
3. 多机调度问题(1)问题描述要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m 台机器加工处理完成。
约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。
作业不能拆分成更小的子作业。
(2)算法实现首先,把作业按加工所用的时间从大到小排序,如果作业数目比机器的数目少或相等,则直接把作业分配下去;如果作业数目比机器的数目多,则每台机器上先分配一个作业,如下的作业分配时,是选那个表头上s最小的链表加入新作业。
五.算法源代码及用户屏幕1. 单源最短路径问题(Dijksa算法)(备注:语言C++,编译器:MS VS2005;共2个文件)/////Graph.h//////////////////////////////////////////////#include<iostream>#include<conio.h>using namespace std;#define MAXPOINT 100class CGraph{bool solved;double graph[MAXPOINT][MAXPOINT];int size;int startPoint;double dist[MAXPOINT];int prev[MAXPOINT];public:CGraph(void);~CGraph(void);bool SetGraph( double g[MAXPOINT][MAXPOINT] ,int startPoint ,int size );bool Dijkstra();void Display();int GetStartPoint();double GetBestWay( int dest , int path[] , int &pathLen );};CGraph::CGraph(void){for( int i = 0 ; i < MAXPOINT ; i++ ){for( int j = 0 ; j < MAXPOINT ; j++ )graph[i][j] = -1;}startPoint = -1;size = -1;solved = false;}CGraph::~CGraph(void){}bool CGraph::SetGraph( double g[MAXPOINT][MAXPOINT] , int startPoint , int size ){for( int i = 0 ; i < size ; i++ ){for( int j = 0 ; j < size ; j++ )graph[i][j] = g[i][j];}this->startPoint = startPoint;this->size = size;solved = false;Dijkstra();return true;}bool CGraph::Dijkstra(){bool s[MAXPOINT];for( int j = 0 ; j < size ; j++ ){dist[j] = graph[startPoint][j];s[j] = false;if( dist[j] < 0 )prev[j] = 0;elseprev[j] = startPoint;}dist[startPoint] = 0;s[startPoint] = true;for( int i = 0 ; i < size ; i++ ){double temp;int u = startPoint;bool flag = false;for( int j = 0 ; j < size ; j++ ){if( !s[j] ){if( flag ){if( dist[j] > 0 && dist[j] < temp ){u = j;temp = dist[j];}//ENDIF}else{u = j;temp = dist[j];flag = true;}//ENDELSE}//ENDIF}//ENDIFs[u] = true;for( int j = 0 ; j < size ; j++ ){if( !s[j] && graph[u][j] > 0 ){double newDist = dist[u] + graph[u][j];if( dist[j] < 0 || newDist < dist[j] ){dist[j] = newDist;prev[j] = u;}}//ENDIF}//ENDFOR}solved = true;return true;}//ENDvoid CGraph::Display(){for( int i = 0 ; i < size ; i++ ){for( int j = 0 ; j < size ; j++ ){printf( "%5.f" , graph[i][j] );}printf( "\n" );}}double CGraph::GetBestWay( int dest , int path[] , int &pathLen ) {int p = dest;int theway[MAXPOINT];int len = 0;while( p != startPoint ){theway[len] = p;p = prev[p];len++;}theway[len] = startPoint;len++;for( int i = 0 , j = len - 1 ; i < len ; i++ , j-- )path[i] = theway[j];pathLen = len;return dist[dest];}int CGraph::GetStartPoint(){return startPoint;}/////main.cpp//////////////////////////////////////////////#include "Graph.h"void main(){double graph[][MAXPOINT] ={{ 0 , 10 , -1 , 30 , 100 },{ -1 , 0 , 50 , -1 , -1 },{ -1 , -1 , 0 , -1 , 10 },{ -1 , -1 , 20 , 0 , 60 },{ -1 , -1 , -1 , -1 , 0 }};int size = 5;int start = 0;int dest = 1;int pathlen;int path[MAXPOINT];double dist;CGraph g;g.SetGraph( graph , start , size );g.Display();printf( "----------------------------------------\n" );for( dest = 0 ; dest < size ; dest++ ){dist = g.GetBestWay( dest , path , pathlen );printf( "path:%d --> %d \nshortest: %.f\n" , g.GetStartPoint() , dest , dist );printf( "nodes::\n" );for( int i = 0 ; i < pathlen ; i++ )printf( "%3d" , path[i] );printf( "\n----------------------------------------\n" );}//ENDFOR_getche();}//END测试数据:{ 0 , 10 , -1 , 30 , 100 },{ -1 , 0 , 50 , -1 , -1 },{ -1 , -1 , 0 , -1 , 10 },{ -1 , -1 , 20 , 0 , 60 },{ -1 , -1 , -1 , -1 , 0 }用户屏幕:2.找零问题(备注:语言:C++;编译环境:C-free3.5;共1个文件)#include<iostream>using namespace std;#define NUM 4void main(){int m[NUM]={25,10,5,1};int n;cout<<"Enter the total money:";cin>>n;cout<<n<<" greedy solution:";for(int i=0;i<NUM;i++)while(n>=m[i]&&n>0){cout<<m[i]<<" ";n-=m[i];}cout<<endl;}测试数据:99测试结果:25,25, 25, 10, 10, 1, 1, 1, 1 用户屏幕:3. 多机调度问题(备注:语言:C++;编译环境:C-free3.5;共1个文件) #include <iostream>using namespace std;#define N 18#define M 5void sort(int t[],int n);int set_work1(int t[],int n);int max(int t[],int num);int min(int t[],int m);int set_work2(int t[],int n);static int time[N]={22,47,23,55,72,1,99,14},s[M]={0,0,0,0,0};void main(){sort(time,N);cout<<"best solution:" ;if(M>=N)cout<<set_work1(time,N)<<endl;elsecout<<set_work2(time,N)<<endl;}void sort(int t[],int n){for(int k=0;k<n-1;k++){int j=k;for (int i=k; i<n; i++)if (t[i]>t[j]) j=i;{int temp=t[j];t[j]=t[k];t[k]=temp;}}//ENDFOR}//ENDint max(int t[],int num){int max=t[0];for(int i=1;i<num;i++)if(max<t[i]) max=t[i];return max;}int min(int t[],int m){int min=0;for(int i=1;i<m;i++)if(s[min]>s[i])min=i;return min;}int set_work1(int t[],int n){int m=0;for(int i=0;i<n;i++)s[m++]+=t[i];return max(s,N);}int set_work2(int t[],int n){for(int i=0;i<n;i++)s[min(s,M)]+=t[i];return max(s,M);}测试数据:time[N]={22,47,23,55,72,1,99,14},s[M]={0,0,0,0,0} 测试结果:Best Solution:99用户屏幕:六.实验过程分析3个试验中,单源最短路径的问题比较麻烦一点,而Dijkstra算法解决了很多的问题,在效率上也比较的优秀;找零问题是比较典型的贪心算法问题,比较简单,以后与理解和实现,所以助于我们理解贪心算法的核心思想;多机调度问题,也很简单,关键在于处理机器数量和作业书的问题上。