搜档网
当前位置:搜档网 › 21、贪婪算法课程设计

21、贪婪算法课程设计

21、贪婪算法课程设计
21、贪婪算法课程设计

数学与计算机学院

课程设计说明书课程名称: 算法设计与分析-课程设计课程代码: 8404101

题目利用贪婪算法实现多种实际问题年级/专业/班:

学生姓名:

学号:

开始时间:2010 年12月26 日完成时间:2011 年01月 9 日

课程设计成绩:

学习态度及平时成绩(30)技术水平与实际

能力(20)

创新(5)说明书撰写质量(45)

总分

(100)

指导教师签名:年月日

目录

一、需求分析 ............................................................................................................................................ - 2 -

1.1问题解决 .................................................................................................................. - 2 -

1.2实现思想 .................................................................................................................. - 2 -

1.3实现意义 .................................................................................................................. - 2 -

二、概要设计 ..................................................................................................................... - 2 -

2.1算法流程 .................................................................................................................. - 2 -

2.2算法证明 .................................................................................................................. - 5 -

2.3存储结构 .................................................................................................................. - 8 -

2.4核心模块 .................................................................................................................. - 8 -

三、详细设计 ................................................................................................................... - 11 -

3.1 一般贪婪法以及K=2阶贪婪启发法0-1背包源程序 ...................................... - 11 -

3.2 贪婪法有限计算机作业调度源程序................................................................... - 16 -

四、调试分析 ................................................................................................................... - 18 -

4.1调试出现问题及分析 ............................................................................................ - 18 -

4.2数据测试与结果 .................................................................................................... - 18 -

4.3时间复杂度 ............................................................................................................ - 20 -

4.4算法改进设想 ........................................................................................................ - 20 -

五、总结 ........................................................................................................................... - 20 -

一、需求分析

1.1问题解决

本次采用贪婪法所解决的问题为:0-1背包问题,异界有限期作业调度问题,分别使得背包中所放物品价值最大,计算机处理作业后所获得利益最大化。在本次贪婪法解决背包问题时,增加了一个K=2阶贪婪启发算法,使得所得解更加接近最优解。

1.2实现思想

贪婪算法主旨是在解决问题的过程中,采用逐步构建最优的方法,从而达到全局最优的解。在每个阶段都作出一个看上去最优的决策(在一定的标准下)。决策一旦作出,就不可再更改。作出贪婪决策的依据称为贪婪准则。

而K=2阶贪婪启发算法,即:首先从当前物品中任意选出K=2件物品,然后放入背包,如果这K=2件物品重量大于背包重量C,则放弃,否则,剩余的容量用来考虑将剩余物品按价值密度(pi/wi)递减的顺序装入。通过考虑由启发法产生的解法中最多为k 件物品的所有可能的子集来得到最优解。此解将更接近实际的最优解。比如:当前背包承重量C=40,物品重量W={25、20、20},物品价值P={25,15,15},一般贪婪法结果为[1,0,0],背包价值为25,而K=2阶贪婪启发算法解为[0,1,1],背包价值为30。

1.3实现意义

通过贪婪法解决0-1背包以及有限期作业调度问题,能够检测我们所学知识掌握是否牢固,同时能够快速有效的解决实际问题,而且能够将此算法思想应用于各个领域,解决不同的问题。

二、概要设计

2.1算法流程

A:贪婪法解决0-1背包问题

开始

WI/Pi 是否是当前最

大值

i ++

输入物品重量以

及价值

计算Wi/Pi

N

Y

Wi 是否小于C (背包当前承重量)n++

Y

放入背包,赋值Wi=无穷大

N&&n

n

结束

n >=N

n>=N

图一

B :K=2阶贪婪启发算法解决0-1背包问题

开始

输入物品重量及对

应价值

计算

Value=(Wi+Wj)

+(Pi+Pj)

Value 是否为当

前最大

Wi+Wj 是否小于背包称重量C

Y

将对应物品放入背

Y

N

放弃此两个物

品N

没有任何i 、j 满

足条件

N

执行一般贪婪算法

图二

C :贪婪法解决有限期限计算机作业调度

开始

输入作业时间T 、期限D 以及对应效益P

计算效益比(Pi\Ti )

是否是当前最

N

完成时是否超期

D

Y

忽略此作业

Y

调入计算机执行

N

结束

N

是否还有满足要求的作业

Y

图三

2.2算法证明

在此证明贪婪启发算法: 1、算法描述及实例分析

对算法的一个改进是一种启发式搜索算法,称为k 阶优化算法。首先将最多k 件物品放入背包,如果这k 件物品重量大于c,则放弃它。否则,剩余的容量用来考虑将剩余物品

按Pi /wi 递减的顺序装入。通过考虑由启发法产生的解法中最多为k 件物品的所有可能的子集来得到最优解[ 5 ] 。给出一个实列来解释该算法的运行过程。考虑n =4, w = [ 2, 4, 6, 7 ] , p = [ 6, 10, 12, 13 ] , c = 11。当k = 0时,背包按物品价值密度3, 2. 5, 2, 1. 86 的非递减顺序装入,首先将物品1放入背包,然后是物品2,背包剩下的容量为11 - 2 - 4= 5个单元,剩下的物品没有一个合适的,因此解为x = [ 1 ,1 , 0 , 0 ]。此解获得的价值为16。现在考虑k = 1时的贪婪启发法。就是依次验证从取定i 对算法的另一个改进思路是一种启发式搜索算法,称为k 阶优化算法。首先将最多k 件物品放入背包,如果这k 件物品重量大于c,则放弃它。否则,剩余的容量用来考虑将剩余物品按pi /wi 递减的顺序装入。通过考虑由启发法产生的解法中最多为k 件物品的所有可能的子集来得到最优解[ 5 ] 。我们给出一个实例来解释该算法的运行过程。考虑n =4, w = [ 2, 4, 6, 7 ] , v = [ 6, 10, 12, 13 ] , c = 11。当k = 0时,背包按物品价值密度3, 2. 5, 2, 1. 86 的非递减顺序装入,首先将物品1放入背包,然后是物品2,背包剩下的容量为11 - 2 - 4= 5个单元,剩下的物品没有一个合适的,因此解为x = [ 1 ,1 , 0 , 0 ]。此解获得的价值为16。

若k = 2,就是依次验证从取定i, j 开始的,然后按物品价值密度非递减得到的最优解,同时和k = 1时的解进行比较。除了考虑k < 2的子集,还必需考虑子集{ 1 , 2 } , { 1 , 3 } ,{ 1 , 4 } , { 2 , 3 } , { 2 , 4 }和{ 3 , 4 }。首先从最后一个子集开始,它是不可行的,故将其抛弃,剩下的子集经求解分别得到如下结果: [ 1 , 1 , 0 , 0 ] , [ 1 , 0 , 1 , 0 ] , [ 1 , 0 ,0 , 1 ] , [ 0 , 1 , 1 , 0 ]和[ 0 , 1 , 0 , 1 ] ,这些结果中最后一个价值为23,它的值比k = 0获得的解要高,这个答案即为k = 2启发式方法产生的结果。

2、近似比的证明

当K=0时,即为一般贪婪算法,当K>=1时:

令op P 为最优解时,对op P 中的物品价值按从大到小排列,得到^

1P 、^

2P ...^

K P ...^

l P ,其中^

1P 到^

k P 必定出现在某个K 阶全排列中。令max P 为该全排列所对应的用K 阶优化法求得解1P 、2P 、3P ,....n P .

现考虑max P 中扣除1P 到k P 得部分,即1+k P 到l P 按照(价值\重量)的递减顺序进行排列,得到1'+k P ...n P '记为L P '。

所有物品集中扣除max P 的剩余物品也按(价值\重量)的递减顺序进行排列。记为

1*+k P ...j P *记为L P *。

再对op P 中扣除1P 到k P 得部分按照(价值\重量)的递减顺序进行排列,得到

'

^

1+k P ...'^l P ,记为L P '

^。

(1)证明max P +'

m P >=op P

考虑将1*+k P ...j P *中的物品顺序装入max P 中k P 之后的位置,设第一个无法装入的为*m P ,现在从*

m P ,...,n P *中顺序查找第一个无法放入max P 中且出现在l P '的成员,记为'

m P 。这样的'

m P 一定存在,因为若不存在,则说明^'

L P 中的物品全部在'

L P 中,此时

max P =op P ,为最优解。

显然若将'm P 再加入max P 中,则超过背包负重。也就是说('L P +'

m P )的重量大于L

P '

^的重量。

由L P '

定义可知L P '

的价值密度大于^

'L P 的价值密度,又由于'

m P 是^

'

L P 的成员,所以有集合('

L P +'

m P )的价值密度大于L P '

^的价值密度。

价值密度X 重量=价值,故('

L P +'

m P )的价值大于L P '

^的价值,即('L P +'

m P )>=L P '

^ 将该不等式左右各加上排列(1P ...k P )的值,得到max P +'

m P >=op P (2)证明'

m P ≤op P /(K+1) 因为'

m P ≤k P ^≤...≤^

1P

所以op P ≥1^P +...+^

K P +'m P ≥(K+1)'

m P 即'

m P ≤op P /(K+1)

(3)由(1)(2)结论知:

op P -max P ≤'

m P ≤1/(k+1)op P 即max P ≥K/(K+1)op P

max P 是K 阶优化算法在进行K 阶计算时的一个解,令算法在K 阶计算的输出结果为op k P -

则有max P ≤op k P -

即有op k P -≥max P ≥K/(K+1)op P

由此可得op P /op k P -≤K/(K+1),即近似比为K/(K+1)。

2.3存储结构

0-1背包以及有限期计算机作业调度,都将其物品重量,物品价值,作业时间,作业效益,作业期限,分别存入一个一维数据中,数组的下标,即表示其对应的该物品编号,有利于操作。

2.4核心模块

0-1背包问题核心模块:

// 贪婪算法,取出当前适合背包重量的,价值密度最大的物品

void take(float value[],int w[],int t[],int c)

{

float tempp[N]; //定义一个数组,将各个物品价值密度复制进去

int tempw[N];//定义一个数组,将各个物品的重量复制进去

int i;

int k=0;

int n=0;

for(i=0;i

{

tempp[i]=value[i];

}

for(i=0;i

{

tempw[i]=w[i];

}

while(n0时,寻找可以放进去且价值密度最大的物品{

float p_max=0;

for(i=0;i

{

if(p_max

{

p_max=tempp[i]; //找出当前的最大价值密度

k=i; //对应物品的序号

}

}

tempp[k]=0;//无论最终是否放入背包,都将其价值密度调为0

if(c>=tempw[k])

{

c=c-tempw[k];

tempw[k]=C;

t[k]=1;

}

else

{

}

n++;

}

}

K=2阶贪婪算法核心模块:

//K=2阶贪婪启发算法解决背包问题

void take_two(int w_two[][N],float value[],int w[],int t[],int c,float p_two[][N])

{

int i,j,k,m;

float p_max=0;

for(i=0;i

for(j=i+1;j

{

if(w_two[i][j]>c)//此2个物品不能放入背包中

{

w_two[i][j]=C;//置物品重量为最大

p_two[i][j]=0; //置物品价值为0

}

}

for(i=0;i

for(j=i+1;j

{

if(p_max

{

p_max=p_two[i][j];//找出2个物品组合能放入背包,且价值最大的

k=i;//分别记录此2个物品位置

m=j;

}

}

if(p_max==0)//p_max=0,说明任何2个物品组合均大于背包承重量

{

take( value,w,t,c);// 按照价值密度大小将剩余物品放入背包

}

else //有2个物品能够放入背包

{

t[k]=1;//将此物品放入背包

t[m]=1;

c=c-w[k]-w[m];//背包承重量减轻

w[k]=C;//对应物品重量置最大

w[m]=C;

value[k]=0;//对应物品价值置0

value[m]=0;

take( value,w,t,c);// 再次按照价值密度大小将剩余物品放入背包

}

}

有限期计算机作业调度核心模块:

//贪婪法实现有效期限计算机作业调度

float jcb(float work_time[],float work_benefit[],float work_deadline[],int t[]) {

int i,j,k;

float temp;

float v=0;

float time=0.0;

for(i=0;i

{

float v_max=0.0;

for(j=0;j

{

temp=float(work_benefit[j]/work_time[j]);//计算此作业效益率

if((v_max

{

v_max=temp;

k=j;//记录此作业的编号

}

}

if(v_max>0)//找到有满足的作业

{

time=time+work_time[k];//记录计算机作业运行时间

t[i]=k+1;//记录执行作业的顺序

v=v+work_benefit[k];//累加所获得的效益

work_benefit[k]=0;//将此作业作废

}

}

return v;//返回总效益

}

三、详细设计

3.1 一般贪婪法以及K=2阶贪婪启发法0-1背包源程序

#define N 3 // 定义现有物品的总数量

#define Q 40 //定义物品随机重量最大值

#define C 30 //定义背包最大的承重量

#include

#include

#include

#include

//利用随机函数,初始化现有的N个物品的重量,并将其存放入数组中

void create_w (int w[])

{

int i;

/* srand((int)time(0));//srand()用来设置rand()产生随机数时的随机数种子,随机种子通过time(0)的返回值得到

for(i=0;i

{

w[i]=1+(int)(Q*rand()/(RAND_MAX+1.0));

}

*/

printf("请定义%d个物品的重量\n",N);

for(i=0;i

{

scanf("%d",&w[i]);//手动定义物品重量

}

}

//键盘定义各个物品的价值

void create_p(float p[])

{

int i;

printf("定义此%d个物品的价值:\n",N);

for(i=0;i

{

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

}

}

//计算N个物品各自的价值密度(价值密度=物品价值/物品重量)

void calculate_v(float value[],int w[],float p[])

{

for(i=0;i

{

value[i]=float(p[i])/float(w[i]);

}

}

// 贪婪算法,取出当前适合背包重量的,价值密度最大的物品

void take(float value[],int w[],int t[],int c)

{

float tempp[N]; //定义一个数组,将各个物品价值密度复制进去

int tempw[N];//定义一个数组,将各个物品的重量复制进去

int i;

int k=0;

int n=0;

for(i=0;i

{

tempp[i]=value[i];

}

for(i=0;i

{

tempw[i]=w[i];

}

while(n0时,寻找可以放进去且价值密度最大的物品{

float p_max=0;

for(i=0;i

{

if(p_max

{

p_max=tempp[i]; //找出当前的最大价值密度

k=i; //对应物品的序号

}

}

tempp[k]=0;//无论最终是否放入背包,都将其价值密度调为0

if(c>=tempw[k])

{

c=c-tempw[k];

tempw[k]=C;

t[k]=1;

}

else

{

n++;

}

}

void calculate_w(int w_two[][N],int w[])//将物品两两取出并存入一个二位数组中

{

int i,j;

for(i=0;i

for(j=i+1;j

{

w_two[i][j]=w[i]+w[j];

}

}

void calculate_p(float p_two[][N],float p[])//计算两两物品的价值并存入一个二位数组中{

int i,j;

for(i=0;i

for(j=i+1;j

{

p_two[i][j]=p[i]+p[j];

}

}

//K=2阶贪婪启发算法解决背包问题

void take_two(int w_two[][N],float value[],int w[],int t[],int c,float p_two[][N])

{

int i,j,k,m;

float p_max=0;

for(i=0;i

for(j=i+1;j

{

if(w_two[i][j]>c)//此2个物品不能放入背包中

{

w_two[i][j]=C;//置物品重量为最大

p_two[i][j]=0; //置物品价值为0

}

}

for(i=0;i

for(j=i+1;j

{

if(p_max

{

p_max=p_two[i][j];//找出2个物品组合能放入背包,且价值最大的

k=i;//分别记录此2个物品位置

m=j;

}

}

if(p_max==0)//p_max=0,说明任何2个物品组合均大于背包承重量

{

take( value,w,t,c);// 按照价值密度大小将剩余物品放入背包

}

else //有2个物品能够放入背包

{

t[k]=1;//将此物品放入背包

t[m]=1;

c=c-w[k]-w[m];//背包承重量减轻

w[k]=C;//对应物品重量置最大

w[m]=C;

value[k]=0;//对应物品价值置0

value[m]=0;

take( value,w,t,c);// 再次按照价值密度大小将剩余物品放入背包

}

}

void main()

{

int w[N];

create_w(w);//初始化现有的N个物品的重量,取值范围[1,Q]

int i,j;

printf("当前%d个物品的各个重量为:\n",N);

for(i=0;i

{

printf("%10d",w[i]);

}

printf("\n");

float p[N];

create_p(p);//初始化现有的N个物品的价值

float value[N];//定义价值密度数组,用于存放对应物品的价值密度大小

float value_two[N][N];

for(i=0;i

for(j=0;j

{

value_two[i][j]=0;

}

calculate_v(value,w,p);//计算N个物品各自的价值密度(价值密度=物品价值/物品重量) printf("现有%d个物品的各个价值为:\n",N);

for(i=0;i

{

printf("%10f",p[i]);

}

printf("\n");

printf("当前%d个物品的各个重量为:\n",N);

for(i=0;i

{

printf("%10d",w[i]);

}

printf("\n");

printf("对应的%d个物品的各个价值密度为:\n",N);

for(i=0;i

{

printf("%10f",value[i]);

}

printf("\n");

printf("当前背包的最大承受重量为:%d\n",C);

int t[N]={0};

int s[N]={0};

float v_max=0;

float v_max_two=0;

take(value,w,t,C);// 贪婪算法,取出当前适合背包重量的,价值密度最大的物品int w_two[N][N];

for(i=0;i

for(j=0;j

{

w_two[i][j]=0;

}

float p_two[N][N];

for(i=0;i

for(j=0;j

{

p_two[i][j]=0;

}

calculate_w(w_two,w);//将物品两两取出并存入一个二位数组中

calculate_p(p_two,p);//计算两两物品的价值并存入一个二位数组中

take_two(w_two,value,w,s,C,p_two);//K=2阶贪婪启发算法解决背包问题

printf("******************************************\n");

printf("贪婪法对应物品是否放入了背包(0:否,1:是)\n");

for(i=0;i

{

printf("%10d",t[i]);

}

printf("\n");

for(i=0;i

{

v_max=v_max+p[i]*t[i];

}

printf("贪婪法取出的背包最大价值为:%f\n",v_max);

printf("******************************************\n");

printf("利用K=2阶贪婪启发算法求解结果为:\n");

printf("对应物品是否放入了背包(0:否,1:是)\n");

for(i=0;i

{

printf("%10d",s[i]);

}

for(i=0;i

{

v_max_two=v_max_two+p[i]*s[i];

}

printf("\n");

printf("K=2阶贪婪启发算法取出的背包最大价值为:%f\n",v_max_two); }

3.2 贪婪法有限计算机作业调度源程序

# define Q 10 //定义每个作业的最长时间

# define N 5//定义现有作业个数

#include

#include

#include

#include

//利用随机函数,初始化现有的N个作业的所需时间,并将其存放入数组中void create_time (float work_time[])

{

int i;

printf("请定义%d个作业的所需时间\n",N);

for(i=0;i

{

scanf("%f",&work_time[i]);//手动定义作业所需时间

}

}

void create_deadline (float work_deadline[])

{

int i;

printf("请定义%d个作业的有效期限\n",N);

for(i=0;i

{

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

}

}

void create_benefit (float work_benefit[])

{

int i;

printf("请定义%d个作业各个在有限期内完成后所得利益\n",N);

for(i=0;i

{

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

}

}

//贪婪法实现有效期限计算机作业调度

float jcb(float work_time[],float work_benefit[],float work_deadline[],int t[]) {

int i,j,k;

float temp;

float v=0;

float time=0.0;

for(i=0;i

{

float v_max=0.0;

for(j=0;j

{

temp=float(work_benefit[j]/work_time[j]);//计算此作业效益率

if((v_max

{

v_max=temp;

k=j;//记录此作业的编号

}

}

if(v_max>0)//找到有满足的作业

{

time=time+work_time[k];//记录计算机作业运行时间

t[i]=k+1;//记录执行作业的顺序

v=v+work_benefit[k];//累加所获得的效益

work_benefit[k]=0;//将此作业作废

}

}

return v;//返回总效益

}

void main()

{

int t[N]={0};

int i;

float value;

float work_time[N];//定义作业运行时间数组

float work_benefit[N];//定义对应作业效益

float work_deadline[N];//定义对应作业期限

create_time(work_time);//初始化作业运行时间

create_benefit(work_benefit);//初始化作业效益

create_deadline(work_deadline);//初始化作业期限

value=jcb(work_time,work_benefit,work_deadline,t);//贪婪法执行调度,并返回总效益

printf("贪婪算法得到的有限期作业调度为:\n");

for(i=0;i

if(t[i]!=0)

printf("%d--->",t[i]);

printf("\n由此得到的最大利益价值为:%f\n",value);

}

四、调试分析

4.1调试出现问题及分析

程序调试的时候,当然出现过很多问题,有些问题很难发现,有些问题当然也容易发现。

首先,就是由于计算0-1背包价值密度的时候,忘记了将所有数据赋值为float型的,导致价值密度的大小不正确,直接影响到了物品的取舍,这个问题在我通过一步一步的断点调试后发现的,很好的解决了。

第二,就是在对K=2阶启发算法调试的时候,其结果总是比一般贪婪算法最优解还低,最后发现是在第一次取出2个物品放入背包后,忘记了所剩下能放一个但不能放两个物品的情况,在经过断点调试后,分析数据后发现了,最后在用K=2阶算法末尾加上前面的一般贪婪算法,问题顺利的解决了。

第三,在进行计算机作业调度,数据效益比数据处理的时候,同样的犯了float数据类型的转换,但是这次错误很隐藏,以至于调试了大半天,检查了所有的地方,才发现,此次数据类型的转换,改正钱,输出结果始终为0,改正后结果立马就对了。

4.2数据测试与结果

测试一般贪婪法和K=2阶贪婪启发法结果如下图,它们都找出了最优解:

再换一组数据,结果如下图,一般贪婪法没能找出最优解,而K=2阶找出了最优解:

贪婪法解决有限期计算机作业调度测试数据及结果如下图:

贪心算法经典例题

贪心算法经典例题 发布日期:2009-1-8 浏览次数:1180 本资料需要注册并登录后才能下载! ·用户名密码验证码找回密码·您还未注册?请注册 您的账户余额为元,余额已不足,请充值。 您的账户余额为元。此购买将从您的账户中扣除费用0.0元。 内容介绍>> 贪心算法经典例题 在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。 从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例1 均分纸牌(NOIP2002tg) [问题描述] 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为: ①9 ②8 ③17 ④ 6 移动3次可达到目的: 从③取 4 张牌放到④(9 8 13 10) -> 从③取 3 张牌放到②(9 11 10 10)-> 从②取 1 张牌放到①(10 10 10 10)。 [输入]:键盘输入文件名。 文件格式:N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) [输出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] a.in: 4 9 8 17 6 屏慕显示:3 算法分析:设a[i]为第i堆纸牌的张数(0<=i<=n),v为均分后每堆纸牌的张数,s为最小移到次数。 我们用贪心法,按照从左到右的顺序移动纸牌。如第i堆(0

【精选】贪心算法的应用

贪心算法的应用 课程名称:算法设计与分析 院系:计算机科学与信息工程学院 学生姓名:**** 学号:********** 专业班级:********************************** 指导教师:****** 201312-27

贪心算法的应用 摘要:顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。贪心算法求问题一般具有两个重要性质:贪心选择性质和最优子结构性质。所谓贪心选择性是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法主要区别。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 背包问题是一个经典的问题,我们可以采用多种算法去求解0/1背包问题,比如动态规划法、分支限界法、贪心算法、回溯法。在这里我们采用贪心法解决这个问题。 关键词:贪心法背包问题最优化

目录 第1章绪论 (3) 1.1 贪心算法的背景知识 (3) 1.2 贪心算法的前景意义 (3) 第2章贪心算法的理论知识 (4) 2.1 问题的模式 (4) 2.2 贪心算法的一般性描述 (4) 第3章背包问题 (5) 3.1 问题描述 (5) 3.2 问题分析 (5) 3.3算法设计 (5) 3.4 测试结果与分析 (10) 第4章结论 (12) 参考文献 (13) 附件 (13)

利用贪婪算法实现多种实际问题

利用贪婪法实现多种实际问题 《算法设计与分析》课程设计任务书 学院名称:数学与计算机学院专业:信息与计算科学专业年级:2007 一、设计题目 题目十四:利用贪婪算法实现多种实际问题 二、主要内容 给出多种可以用贪婪算法解决的典型问题,并分析、证明、编程。 三、具体要求 (1)贪婪算法的基本思想; (2)给出背包问题的贪婪算法; (3)给出有限期计算机作业调度的贪婪算法; (4)给出上面两个算法的证明; (5)给出上面两个算法的程序。 (6)给出时间复杂度。 四、主要技术路线提示 在用贪婪算法解决资源分配问题、布线问题、0-1背包问题过程中,使用贪婪算法解决问题,通常需要做好以下几个方面的工作: 1、明确问题的求解目标。 2、分析问题所包含的约束条件。 3、建立优化函数。优化函数通常可以通过综合分析问题的求解目标及约束条件归纳出来。 4、制定贪婪准则。 五、进度安排 1、第一周:分析题目的需求,设计抽象数据类型、构思算法、通过类的设计实现抽象数据类型并编写上机程序 2、第二周完成程序开发,进行测试并分析结果,最后撰写课程设计报告 I

利用贪婪法解决实际问题 六、完成后应上交的材料 上交的成果的内容必须由以下四个部分组成,缺一不可。 1.上交源程序:学生按照课程设计的具体要求所开发的所有源程序(应该放到一个文件夹中)。 2.上交程序的说明文件:(保存在.txt中),在说明文档中应该写明上交程序所在的目录,上交程序的主程序文件名,如果需要安装,要有程序的安装使用说明。 3.课程设计报告电子文档:(保存在word 文档中,文件名要求按照“学号姓名算法分析课设报告.doc”起名,如文件名为“200300109张三算法分析课设报告.doc”),按照课程设计的具体要求建立的功能模块,每个模块要求按照如下几个内容认真完成: 其中包括: (1)需求分析: 在该部分中叙述每个模块的功能要求等。 (2)概要设计 在此说明每个部分的算法设计说明(可以是描述算法的流程图),每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义。 (3)详细设计 各个算法实现的源程序,对每个题目要有相应的源程序(可以是一组源程序,每个功能模块采用不同的函数实现)。 源程序要按照写程序的规则来编写。要结构清晰,重点函数的重点变量,重点功能部分要加上清晰的程序注释。 (4)调试分析 包括测试数据,测试输出的结果,时间复杂度分析,和每个模块设计和调试时存在问题的思考(问题是哪些?问题如何解决?),算法的改进设想。 (5)课设总结 总结可以包括:课程设计过程的收获、遇到问题、遇到问题解决问题过程的思考、程序调试能力的思考、对算法设计与分析这门课程的思考、在课程设计过程中对《算法设计与分析》课程的认识等内容。 4.课程设计报告打印稿。 七、推荐参考资料 教材: 《算法设计与分析》 Anany Levitin 著潘彦译清华大学出版社,2007。 《算法设计与分析》宋文等编重庆大学出版社,2001。 参考书:[1] 《算法设计与分析》周培德电子工业出版社,2000。 [2] 《算法设计与分析》王晓东电子工业出版社,2004 指导教师签名日期年月日 系主任审核日期年月日 II

贪心算法详解分析

贪心算法详解 贪心算法思想: 顾名思义,贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。 贪心算法的基本要素: 1.贪心选择性质。所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。 动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。 对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。 2. 当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的 最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。 贪心算法的基本思路: 从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到算法中的某一步不能再继续前进时,算法停止。 该算法存在问题: 1. 不能保证求得的最后解是最佳的; 2. 不能用来求最大或最小解问题; 3. 只能求满足某些约束条件的可行解的范围。 实现该算法的过程: 从问题的某一初始解出发; while 能朝给定总目标前进一步do 求出可行解的一个解元素; 由所有解元素组合成问题的一个可行解; 用背包问题来介绍贪心算法: 背包问题:有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要 求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

贪婪算法在排课问题中分析与应用

贪婪算法在排课问题中分析与应用 摘要:排课问题是教学管理中重要的问题,对教学质量起到十分重要的影响。随着计算机和信息技术的快速发展,通过合理的算法编制排课系统是十分合适的。本文通过排课问题算法的分析,选择贪婪算法来解决排课问题。通过实验表明,目前的算法能够很好的解决排课问题,对问题的解决的复杂度大大降低,使得排课变得十分简单和高效。 关键字:排课,贪婪算法,优先级 1、绪论 在高校日常管理中,教学计划是重要的组成部分。而教学计划的重要体现方式之一就是排课表,其在教学管理中的地位和作用不可低估,课表的管理对教学管理是起到基础和重要的作用。因此排课问题是教学管理中重要的问题,对教学质量起到十分重要的影响。 由于上课约束条件多,课表的编制十分复杂,是一个耗时耗力的工作。目前随着高校人数的越来越多,其很难用手工去编制课表,其工作时间长,工作量大和繁琐的编制过程是一般人很难驾驭的。随着计算机和信息技术的快速发展,通过合理的算法编制排课系统是十分合适的。通过计算机算法的求解来对问题进行抽象和解决。 2、排课算法算法简介 目前对于排课问题的算法较多,主要有蚁群算法、模拟退火算法、遗传算法、整数规划法和贪婪算法等。 (1)蚁群算法 蚁群算法就是将模拟蚂蚁的活动,对参数设置较少。这种算法具备较强的全局搜索能力,但其效率较低,且容易出现停滞[1]。 (2)模拟退火算法 这个算法被较多的学者用来解决排课问题,它是模拟退火的现象,对自然事物进行抽象而来。其比较适合约束条件较少的问题。如果约束条件少,其很快就能获得最优解。但这种算法的参数选择较难,且资源开销大[2]。 (3)遗传算法 遗传算法是基于自然选择和生物遗传的全局优化策略。其优点在于在非线性问题上能够表现出全局最优,可以并行处理而且算法效率相对较高[3]。 但遗传算法本身较为复杂,由于排课问题的约束条件较多,其算法的效率较低,如果排课要求十分严格的话,很有可能造成找不到解。 (4)整数规划法 整数规划法来解决排课问题计算量很大,只适合规模较小排课问题,对于规模较大的,至今都很难找到一个可行算法。 (5)贪婪算法 贪婪算法是指在解决问题的时候,不会考虑整体最优,而是采取局部最优的思想进行最优思想[4]。也就是说,该算法将解决问题分解为每一个步骤,根据其难易程度进行解决,通过满足局部最优的方式来尽可能的获得最满意的解决。虽然在某些情况下,贪婪算法并不能得到最优解,但能得到相对满意的解。 3、排课问题综述 (1)排课原则 排课问题的本质是一个优化问题,是对教师、上课课程、上课时间和上课地点等因素的优化。其目的就是将全校所开设课程在有限的时间和地点下进行合理的安排,确保教学的顺利进行,以达到最优的效果。 为了能够产出一张满意合格的排课表,在排课中要满足一些约束条件。我们将一些约束

算法分析与设计选修课-贪心算法应用研究

武汉理工大学 算法设计与分析论文题目:贪心算法应用研究 姓名:吴兵 学院:信息工程 专业班级:电子133 学号: 1409721303131 任课教师:张小梅

目录 摘要 (1) 1.绪论 (2) 2贪心算法的基本知识概述 (3) 2.1 贪心算法定义 (3) 2.2 贪心算法的基本思路及实现过程 (3) 2.3贪心算法的核心 (3) 2.4贪心算法的基本要素 (4) 2.5 贪心算法的理论基础 (6) 2.6 贪心算法存在的问题 (7) 3贪心算法经典应用举例 (8) 3.1删数问题 (8) 3.2 汽车加油问题 (10) 3.3会场安排问题 (12) 4.总结 (16) 5.参考文献 (17)

摘要 在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。贪心算法所作的选择可以依赖于以往所作过的选择,但决不依赖于将来的选择,也不依赖于子问题的解,因此贪心算法与其它算法相比具有一定的速度优势。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。本文讲述了贪心算法的含义、基本思路及实现过程,贪心算法的核心、基本性质、特点及其存在的问题。并通过贪心算法的特点举例列出了以往研究过的几个经典问题,对于实际应用中的问题,也希望通过贪心算法的特点来解决。 关键词:贪心算法最小生成树多处最优服务次序问题删数问题

贪心算法的应用

从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例1 均分纸牌(NOIP2002tg) [问题描述] 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为: ①9 ②8 ③17 ④6 移动3次可达到目的: 从③取 4 张牌放到④(9 8 13 10) -> 从③取 3 张牌放到②(9 11 10 10)-> 从②取 1 张牌放到①(10 10 10 10)。 [输入]:键盘输入文件名。 文件格式:N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) [输出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] : 4 9 8 17 6 屏慕显示:3 算法分析:设a[i]为第i堆纸牌的张数(0<=i<=n),v为均分后每堆纸牌的张数,s为最小移到次数。 我们用贪心法,按照从左到右的顺序移动纸牌。如第i堆(0v,则将a[i]-v张纸牌从第I堆移动到第I+1堆; (2)若a[i]

贪婪算法

答:贪婪算法(Greedy algorithm)是一种对某些求最优解问题的更简单、更迅速的设计技术。用贪婪法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。 贪婪算法是一种改进了的分级处理方法。其核心是根据题意选取一种量度标准。然后将这多个输入排成这种量度标准所要求的顺序,按这种顺序一次输入一个量。如果这个输入和当前已构成在这种量度意义下的部分最佳解加在一起不能产生一个可行解,则不把此输入加到这部分解中。这种能够得到某种量度意义下最优解的分级处理方法称为贪婪算法。 对于一个给定的问题,往往可能有好几种量度标准。初看起来,这些量度标准似乎都是可取的,但实际上,用其中的大多数量度标准作贪婪处理所得到该量度意义下的最优解并不是问题的最优解,而是次优解。因此,选择能产生问题最优解的最优量度标准是使用贪婪算法的核心。 一般情况下,要选出最优量度标准并不是一件容易的事,但对某问题能选择出最优量度标准后,用贪婪算法求解则特别有效。最优解可以通过一系列局部最优的选择即贪婪选择来达到,根据当前状态做出在当前看来是最好的选择,即局部最优解选择,然后再去解做出这个选择后产生的相应的子问题。每做一次贪婪选择就将所求问题简化为一个规模更小的子问题,最终可得到问题的一个整体最优解。其有以下特性: ⑴ 有一个以最优方式来解决的问题。为了构造问题的解决方案,有一个候选的对象的集合:比如不同面值的硬币。 ⑵ 随着算法的进行,将积累起其它两个集合:一个包含已经被考虑过并被选出的候选对象,另一个包含已经被考虑过但被丢弃的候选对象。 ⑶ 有一个函数来检查一个候选对象的集合是否提供了问题的解答。该函数不考虑此时的解决方法是否最优。 ⑷ 还有一个函数检查是否一个候选对象的集合是可行的,也即是否可能往该集合上添加更多的候选对象以获得一个解。和上一个函数一样,此时不考虑解决方法的最优性。 ⑸ 选择函数可以指出哪一个剩余的候选对象最有希望构成问题的解。 ⑹ 最后,目标函数给出解的值。

贪心算法设计与应用

实验报告 课程算法设计与分析实验实验名称贪心算法设计与应用第 1 页一、实验目的 理解贪心算法的基本原理,掌握贪心算法设计的基本方法及其应用; 二、实验内容 (一)Huffman编码和译码问题: 1.问题描述 给定n个字符在文件中的出现频率,利用Huffman树进行Huffman编码和译码。设计一个程序实现: 1.输入含n(n<=10)个字符的字符集S以及S中各个字符在文件中的出现频 率,建立相应的Huffman树,求出S中各个字符的Huffman编码。 2.输入一个由S中的字符组成的序列L,求L的Huffman 编码。 3. 输入一个二进制位串B,对B进行Huffman译码,输出对应的字符序列; 若不能译码,则输出无解信息。 提示:对应10 个字符的Huffman树的节点个数<211。 2.测试数据 Input n=5 字符集合S={a, b, c, d, e}, 对应的频率分别为 a: 20 b: 7 c: 10 d: 4 e: 18 字符序列L=ebcca 二进制位串B=01100111010010 Output S中各个字符的Huffman编码:(设Huffman树中左孩子的权<=右孩子的权)a: 11 b: 010 c: 00 d: 011 e: 10 L的Huffman 编码:10010000011 B对应的字符序列: dcaeeb 若输入的B=01111101001,则无解 (二) 加油问题(Problem Set 1702): 1.问题描述 一个旅行家想驾驶汽车从城市A到城市B(设出发时油箱是空的)。给定两个

城市之间的距离dis、汽车油箱的容量c、每升汽油能行驶的距离d、沿途油站数n、油站i离出发点的距离d[i]以及该站每升汽油的价格p[i],i=1,2,…,n。设d[1]=0=xw和yb>=yw。 若黑点b支配白点w,则黑点b和白点w可匹配(可形成一个匹配对)。在一

贪心算法的应用实例

贪心算法的应用实例 例2.排队问题 【题目描述】 在一个医院B 超室,有n个人要做不同身体部位的B超,已知每个人需要处理的时间为ti,(00,从而新的序列比原最优序列好,这与假设矛盾,故s1为最小时间,同理可证s2…sn依次最小。 例3.:数列极差问题 【题目描述】 在黑板上写了N个正整数做成的一个数列,进行如下操作:每一次擦去其中的两个数a 和b,然后在数列中加入一个数a×b+1,如此下去直至黑板上剩下一个数,在所有按这种操作方式最后得到的数中,最大的max,最小的为min,则该数列的极差定义为M=max-min。 编程任务:对于给定的数列,编程计算出极差M。 输入输出样例: 输入: 4 2 1 4 3 输出: 13 【算法分析】 当看到此题时,我们会发现求max与求min是两个相似的过程。若我们把求解max与min的过程分开,着重探讨求max的问题。 下面我们以求max为例来讨论此题用贪心策略求解的合理性。 讨论:假设经(N-3)次变换后得到3个数:a ,b , max'(max'≥a≥b),其中max'是(N-2)个数经(N-3)次f变换后所得的最大值,此时有两种求值方式,设其所求值分别为 z1,z2,则有:z1=(a×b+1)×max'+1,z2=(a×max'+1)×b+1所以z1-z2=max'-b≥0若经(N-2)次变换后所得的3个数为:m,a,

贪心算法浅析

贪心算法浅析 摘要:本文讲述了贪心算法的基本思路及实现过程,贪心算法的特点、存在的问题以及应用。并通过贪心算法的特点举例列出了几个经典问题,通过对问题的探讨和研究,对贪心算法有了更加深入的了解。 关键词:贪心算法;最优解;最优子结构问题;删数问题;活动安排问题 贪心算法的基本思路及实现过程 1贪心的基本思想 用局部解构造全局解,即从问题的某一个初始解逐步逼近给定的目标,以尽可能快地求得更好的解。当某个算法中的某一步不能再继续前进时,算法停止。贪心算法思想的本质就是分治,或者说:分治是贪心的基础。每次都形成局部最优解,换一种方法说,就是每次都处理出一个最好的方案。 利用贪心策略解题,需要解决两个问题: (1)该题是否适合于用贪心策略求解; (2)如何选择贪心标准,以得到问题的最优/较优解。 2贪心算法的实现过程 (1)应用同一规则F,将原问题变为一个相似的、但规模更小的子问题; (2)从问题的某一初始解出发: While(能朝给定目标前进一步) 求出可行解的一个解元素; (3)由所有解元素组合成问题的一个可行解。 贪心算法的特点 贪心算法的最大特点就是快,通常是线性二次式,不需要多少额外的内存。一般二次方级的存储要浪费额外的空间,而且那些空间经常得不出正解。但是,使用贪心算法时,这些空间可以帮助算法更容易实现且更快执行。如果有正确贪心性质存在,那么一定要采用。因为它容易编写,容易调试,速度极快,并且节约空间。几乎可以说,此时它是所有算法中最好的。但是应该注意,贪心算法有两大难点:

(1)如何贪心 怎样用一个小规模的解构造更大规模的解呢?总体上,这与问题本身有关。但是大部分都是有规律的。正因为贪心有如此性质,它才能比其他算法快。 具有应当采用贪心算法的问题,当“贪心序列”中的每项互异且当问题没有重叠性时,看起来总能通过贪心算法取得(近似)最优解的。或者,总有一种直觉在引导我们对一些问题采用贪心算法。其中“找零钱”这个问题就是一个例子。题中给出的硬币面值事实上具有特殊性,如果面值发生变化,可能贪心算法就不能返回最优解了。但是,值得指出的是,当一个问题具有多个最优解时,贪心算法并不能求出所有最优解。另外,我们经过实践发现,单纯的贪心算法是顺序处理问题的;而且每个结果是可以在处理完一个数据后即时输出的。 (2)贪心的正确性 要证明贪心性质的正确性,才是贪心算法的真正挑战,因为并不是每次局部最优解都会与整体最优解之间有联系,往往靠贪心算法生成的解不是最优解。这样,贪心性质的证明就成了贪心算法正确的关键。对某些问题贪心性质也许是错的,即使它在大部分数据中都是可行的,但还必须考虑到所有可能出现的特殊情况,并证明该贪心性质在这些特殊情况中仍然正确。而这样容易陷入证明不正确贪心性质的泥塘中无法自拔,因为贪心算法的适用范围并不大,而且有一部分极难证明,若是没有把握,最好不要冒险,还有其他算法会比它要保险。 贪心算法存在的问题 (1)不能保证求得的最后解是最佳的。由于贪心策略总是采用从局部看来是最优的选择,因此并不从整体上加以考虑; (2)贪心算法只能用来求某些最大或最小解的问题; (3)贪心算法只能确定某些问题的可行性范围 贪心算法的应用 1哈夫曼编码 2 0-1背包问题 3磁盘文件的存储 4生产调度问题 5信息查询

贪婪算法思想及其应用

贪婪算法思想及其应用 摘要:贪婪算法也称作贪心算法,它没有固定的算法框架,算法设计的关键是贪婪策略的选择,并且所选的贪婪策略要具有无后向性。 关键词:贪婪策略,无后向性,最优 正文: 一.贪婪算法的定义: 贪婪算法又叫登山法,它的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简单但适用范围有限的策略。 二.贪婪算法思想: 贪婪算法采用逐步构造最优解的方法,即在每个阶段,都选择一个看上去最优的策略(在一定的标准下)。策略一旦选择就不可再更改,贪婪决策的依据称为贪婪准则,也就是从问题的某一个初始解出发并逐步逼近给定的目标,以尽可能快的要求得到更好的解。而且它在设计时没有固定的框架,关键在于贪婪策略的选择。但要注意的是选择的贪婪策略要具有无后向性,即某阶段状态一旦确定下来后,不受这个状态以后的决策的影响,也就是说某状态以后的过程不会影响以前的状态,只与当前状态有关。 三.贪婪算法的优缺点: 贪婪算法的优点在于在求解问题的每一步它都是选择最优解,这样算法就容易实现也易于理解,同时也提高了效率并节省了时间。然而贪婪算法的缺点也是不容忽视的,由于它采取逐步获得最优解的方法而不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。因此贪婪算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题它都能得出整体最优解或者是整体最优解的近似解。 四. 实例参考: 下面就列举用贪婪算法成功得出问题最优解的例子: 例:一个小孩拿着一美元去商店买糖果,花了33美分,售货员需要找回67美分给小孩,而美分的面值有25,10,5,1这几种。问题是售货员找个小孩的钱币的个数应是最少的,但同时要满足67美分这个条件。 分析:选择硬币时所采用的贪婪准则如下:每一次都选择面值最大的货币来凑足要找的零钱总数,但前提是不能超出要找的67美分。 解:我们用贪婪算法来处理这个问题,首先我们肯定会选择面值为25的货币,这样的货币我们需要两枚,然后我们依据贪婪准则选择面值为10的货币,这样的货币我们需要一枚,接着继续选择面值为5的货币一枚和面值为1的货币两枚。这样我们用贪婪算法就得到了解决问题的办法,而在实际中这也确实是这个问题的最优解。因此在找钱这个问题上,我们采用贪婪算法就能满足我们找出的钱的个数最少这个条件。 贪婪算法同时也有很多无法得出最优解的例子,比如我们熟知的背包问题: 例:有一个背包,容量是M=150。有7个物品,物品不能分割成任意大小。 要求尽可能让装入背包中的物品的总价值最大,但不能超过总容量。 物品:A B C D E F G 重量:35 30 60 50 40 10 25 价值:10 40 30 50 35 40 30 在使用贪婪算法的前提下解决下列问题,能否得到最优结果?

贪婪算法在资源分配问题中的应用----彭鹏

贪婪算法在资源分配问题中的应用 彭鹏 贵州财经学院研究生 摘要:贪婪算法的典型应用是解决优化问题,这类算法的策略是只顾眼前,而不考虑以后的影响,它的算法简单容易设计实现,因此在许多实际问题中得到广泛的应用,但是它也存在许多的问题,巧妙的使用贪婪思想,将其融入到资源分配问题中解题中,资源分配问题便焕发出了新的光彩。 本文首先对贪婪算法的基本概念做了介绍,然后通过实例论述了贪婪算法在资源分配问题中的应用。 关键字:贪婪算法研究应用资源分配问题 第一章贪婪算法的概念 1.1什么是贪婪算法 贪婪算法是一种对某些求最优解问题的更简单、更迅速的设计技术。用贪婪法设计算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,它省去了为找最优解要穷尽所有可能而必须耗费的大量时间,它采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择就将所求问题简化为一个规模更小的子问题, 通过每一步贪心选择,可得到问题的一个最优解,虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪婪法不要回溯。 贪婪算法是一种改进了的分级处理方法。其核心是根据题意选取一种量度标准。然后将这多个输入排成这种量度标准所要求的顺序,按这种顺序一次输入一个量。如果这个输入和当前已构成在这种量度意义下的部分最佳解加在一起不能产生一个可行解,则不把此输入加到这部分解中。这种能够得到某种量度意义下最优解的分级处理方法称为贪婪算法。 对于一个给定的问题,往往可能有好几种量度标准。初看起来,这些量度标准似乎都是可取的,但实际上,用其中的大多数量度标准作贪婪处理所得到该量度意义下的最优解并不是问题的最优解,而是次优解。因此,选择能产生问题最优解的最优量度标准是使用贪婪算法的核心。 一般情况下,要选出最优量度标准并不是一件容易的事,但对某问题能选择出最优量度标准后,用贪婪算法求解则特别有效。最优解可以通过一系列局部最优的选择即贪婪选择来达到,根据当前状态做出在当前看来是最好的选择,即局部最优解选择,然后再去解做出这个选择后产生的相应的子问题。每做一次贪婪选择就将所求问题简化为一个规模更小的子

实验1 贪心算法应用及设计

实验一贪心算法应用及设计 实验课时:6学时 二、实验目的: (1)理解贪心选择算法的思想 (2)熟悉单源、哈夫曼、最小生成树等问题的算法; (3)通过对例题分析、设计、调试,体会和掌握贪心法在程序设计中的应用,并进行贪心优化的相应练习。 二、实验原理: 贪心选择算法思想: (1)贪心选择能得到问题的最优解,要证明我们所做的第一步选择一定包含在一个最优解,即存在一个最优解的第一步是从我们的贪心选择开始。 (2)在做出第一步贪心选择后剩下的子问题应该是和原问题类似的规模较小的子问题 为此我们可以用数学归纳法来证明贪心选择能得到问题的最优解。 三、实验内容: 1、活动安排问题。 问题:有n个活动的集合A={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。 求解:安排尽量多项活动在该场地进行,即求A的最大相容子集。 设待安排的11个活动的开始时间和结束时间按结束时间的升序排列如下: 将此表数据作为实现该算法的测试数据。 (1)给出算法基本思想; (2)给出用C/C++或java语言实现程序的代码;

public class actionarrange { public static void main(String []args) { int start[]={1,3,0,5,3,5,6,8,8,2,12}; int finish[]={4,5,6,7,8,9,10,11,12,13,14}; boolean arrange[]=new boolean[10]; for(int i=0;i<10;i++){ arrange[i]=false; } int cout=greedySelector(start,finish,arrange); System.out.println("安排的活动数目:"+cout); } public static int greedySelector(int s[],int f[], boolean a[]) { int n=s.length-1; a[0]=true; System.out.println("活动安排情况如下:"); System.out.println("活动序号开始时间结束时间"); System.out.println(" "+0+" "+s[0]+" "+f[0]); int j=1; int count=1; for (int i=1;i=f[j]) { a[i]=true; j=i; count++; System.out.println(" "+i+" "+s[i]+" "+f[i]); } else a[i]=false; } return count; } }

贪心算法

贪心算法的基本思想是找出整体当中每个小的局部的最优解,并且将所有的这些局部最优解合起来形成整体上的一个最优解。因此能够使用贪心算法的问题必须满足下面的两个性质: 1.整体的最优解可以通过局部的最优解来求出; 2.一个整体能够被分为多个局部,并且这些局部都能够求出最优解。使用贪心算法当中的两个典型问题是活动安排问题和背包问题。 在对问题求解时,总是作出在当前看来是最好的选择。也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解(是否是全局最优,需要证明)。 特别注意:若要用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解!! 以经典的活动安排为例: 1、若A是E的最优解,那么E-A 也是问题的最优解,在余下的问题里,继续拿最早结束的; 2、拿可以开始的最早结束。(所以要按结束时间排序一次,然后把可以开始的选择上,然后继续向后推) 贪心子结构是独立的(往往用标志判断而已),不同于动态规划(后面每一边的计算要用到前一步的值,另外开辟空间来保存) 贪心算法的基本步骤: 1、从问题的某个初始解出发。 2、采用循环语句,当可以向求解目标前进一步时,就根据局部最优策略,得到一个部分解,缩小问题的范围或规模。 3、将所有部分解综合起来,得到问题的最终解。 如最经典的活动安排问题,按结束时间从小到大排序,这样找出第一个节目后,剩下的节目已经是最safe的子结构了,再从子结构中最最早结束但又不和上一次观看的节目有冲突的节目 void arrange(int s[],int f[],bool A[],int n) { A[0] = true; int lastSelected = 0; for (int i = 1;i

Matlab中贪婪算法求解背包问题的研究与应用

Matlab中贪婪算法求解背包问题的研究与应用 晏 杰 【摘 要】本文对贪婪算法进行了分析,总结了贪婪算法解决问题的思路,根据改进的贪婪算法解决策略,通过Matlab对贪婪算法在背包问题中的应用进行了具体实现和详细的分析. 【期刊名称】赤峰学院学报(自然科学版) 【年(卷),期】2012(000)017 【总页数】2 【关键词】Matlab;贪婪算法;背包;研究与应用 1 引言 为了满足人们对大数据量信息处理的渴望,为解决各种实际问题,计算机算法学得到了飞速的发展,线性规划、动态规划、贪婪策略等一系列运筹学模型纷纷运用到计算机算法学中,产生了解决各种现实问题的有效算法.贪婪算法主要用于设计数值最优化问题的算法,它是一种求最优解问题的最直接的设计技术,它不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题能产生整体最优解或者整体最优解的近似解.算法容易实现也易于理解,这使得算法在编码和执行的过程中都有着一定的速度优势,同时也提高了效率并节省了时间. 2 贪婪算法概述 2.1 贪婪算法的定义 贪婪算法又叫登山法,它的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简单但适用范围有限的策略. 2.2 贪婪算法思想 贪婪算法采用逐步构造最优解的方法,即在每个阶段,都选择一个看上去最优的策略(在一定的标准下).策略一旦选择就不可再更改,贪婪决策的依据称为贪婪准则,也就是从问题的某一个初始解出发并逐步逼近给定的目标,以尽可能快的要求得到更好的解.而且它在设计时没有固定的框架,关键在于贪婪策略的选择.但要注意的是选择的贪婪策略要具有无后向性,即某阶段状态一旦确定下来后,不受这个状态以后的决策的影响,也就是说某状态以后的过程不会影响以前的状态,只与当前状态有关. 2.3 贪婪算法的特性 贪婪算法及贪婪算法可解决的问题通常大部分都有如下的特性:

贪婪算法

Greedy Algorithm:贪心算法 算法思想 在贪婪算法中采用逐步构造最优解的方法。在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。决策一旦作出,就不可再更改。作出贪婪决策的依据称为贪婪准则(greedy criterion),也就是从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。当达到某算法中的某一步不能再继续前进时,算法停止。 虽然设计一个好的求解算法更像是一门艺术,而不像是技术,但仍然存在一些行之有效的能够用于解决许多问题的算法设计方法,你可以使用这些方法来设计算法,并观察这些算法是如何工作的。一般情况下,为了获得较好的性能,必须对算法进行细致的调整。但是在某些情况下,算法经过调整之后性能仍无法达到要求,这时就必须寻求另外的方法来求解该问题。Greedy Algorithm在设计方面不能保证求得的最后解是最佳的和不能用来求最大或最小解问题,只能求满足某些约束条件的可行解的范围。 Example1 例1-4 [找零钱] 一个小孩买了价值少于1美元的糖,并将1美元的钱交给售货员。售货员希望用数目最少的硬币找给小孩。假设提供了数目不限的面值为2 5美分、1 0美分、5美分、及1美分的硬币。售货员分步骤组成要找的零钱数,每次加入一个硬币。选择硬币时所采用的贪婪准则如下:每一次选择应使零钱数尽量增大。为保证解法的可行性(即:所给的零钱等于要找的零钱数),所选择的硬币不应使零钱总数超过最终所需的数目。 假设需要找给小孩6 7美分,首先入选的是两枚2 5美分的硬币,第三枚入选的不能是2 5美分的硬币,否则硬币的选择将不可行(零钱总数超过6 7美分),第三枚应选择1 0美分的硬币,然后是5美分的,最后加入两个1美分的硬币。 贪婪算法有种直觉的倾向,在找零钱时,直觉告诉我们应使找出的硬币数目最少(至少是接近最少的数目)。可以证明采用上述贪婪算法找零钱时所用的硬币数目的确最少(见练习1)。 Example2 例1-5 [机器调度] 现有n 件任务和无限多台的机器,任务可以在机器上得到处理。每件任务的开始时间为si,完成时间为fi ,si < fi 。[si , fi ] 为处理任务i 的时间范围。两个任务i,j 重指两个任务的时间范围区间有重叠,而并非是指i,j 的起点或终点重合。例如:区间[ 1,4 ]与区间[ 2,4 ]重叠,而与区间[ 4,7 ]不重叠。一个可行的任务分配是指在分配中没有两件重叠的任务分配给同一台机器。因

贪心算法

贪心算法 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。 贪心法是指从问题的初始状态出发,通过若干次的贪心选择而得出最优解或较优解的一种阶梯方法。事实上,从贪心算法“贪心”一词便可以看出,贪心法总是做出在当前看来是最优的选择,也就是说贪心法不是从整体上加以考虑他所做出的选择只是在某种意义上的局部最优解,而血多问题自身的特性决定了该题可以用贪心算法就能得到最优解。 贪心算法的基本思路 1.建立数学模型来描述问题。 2.把求解的问题分成若干个子问题。 3.对每一子问题求解,得到子问题的局部最优解。 4.把子问题的解局部最优解合成原来解问题的一个解。 实现该算法的过程: 从问题的某一初始解出发; while 能朝给定总目标前进一步 do 求出可行解的一个解元素; 由所有解元素组合成问题的一个可行解。

【问题举例】 11-1-1 购买新年贺卡 问题描述: 新年快到了,笑笑打算给他的好友们发新年贺卡,而且他已经选好了子要购买的样式。俗话说得好,货比三家,笑笑来到了商店,看了各个商铺同一种贺卡的价钱。不仅如此,笑笑还记住了每个商铺的存货量。已知笑笑打算购买m 张贺卡,问他最少花多少钱。 输入格式: 第一行有两个整数m和n。其中m表示要购买的贺年卡的数量,n表示商铺的个数。以下n行,每行有两个整数,分别表示该商铺这种贺年卡的单价和存货量。 输出格式: 进一个数,表示笑笑所化的最少的钱数。 输入样例: 10 4 4 3 6 2 8 10 3 6 输出样例: 36 数据规模: 0

相关主题