贪心算法的应用

贪心算法的应用
贪心算法的应用

在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。

从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。

我们看看下面的例子

例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

(1)若a[i]>v,则将a[i]-v张纸牌从第I堆移动到第I+1堆;

(2)若a[i]

为了设计的方便,我们把这两种情况统一看作是将a[I]-v张牌从第I堆移动到第I+1堆;移动后有:

a[I]:=v;a[I+1]:=a[I+1]+a[I]-v;

在从第i+1堆中取出纸牌补充第i堆的过程中,可能会出现第i+1堆的纸牌数小于零(a[i+1]+a[i]-v<0 )的情况。

如n=3,三堆纸牌数为(1,2,27)这时v=10,为了使第一堆数为10,要从第二堆移9张纸牌到第一堆,而第二堆只有2张纸牌可移,这是不是意味着刚才使用的贪心法是错误的呢?

我们继续按规则分析移牌过程,从第二堆移出9张到第一堆后,第一堆有10张纸牌,第二堆剩下-7张纸牌,再从第三堆移动17张到第二堆,刚好三堆纸牌数都是10,最后结果是对的,从第二堆移出的牌都可以从第三堆得到。我们在移动过程中,只是改变了移动的顺序,而移动的次数不变,因此此题使用贪心法是可行的。

源程序:

var

i,n,s:integer;v:longint;

a:array[1..100]of longint;

f:text;fil:string;

begin

readln(fil);

assign(f,fil);reset(f);

readln(f,n);v:=0;

for i:=1 to n do begin

read(f,a[i]); inc(v,a[i]);

end;

v:=v div n; {每堆牌的平均数}

for i:=1 to n-1 do

if a[i]<>v then {贪心选择}

begin

inc(s);{移牌步数计数}

a[i+1]:=a[i+1]+a[i]-v;{使第i堆牌数为v}

end;{then}

writeln(s);

end.

利用贪心算法解题,需要解决两个问题:

一是问题是否适合用贪心法求解。我们看一个找币的例子,如果一个货币系统有3种币值,面值分别为一角、五分和一分,求最小找币数时,可以用贪心法求解;如果将这三种币值改为一角一分、五分和一分,就不能使用贪心法求解。用贪心法解题很方便,但它的适用范围很小,判断一个问题是否适合用贪心法求解,目前还没有一个通用的方法,在信息学竞赛中,需要凭个人的经验来判断何时该使用贪心算法。

二是确定了可以用贪心算法之后,如何选择一个贪心标准,才能保证得到问题的最优解。在选择贪心标准时,我们要对所选的贪心标准进行验证才能使用,不要被表面上看似正确的贪心标准所迷惑,如下面的列子。

例2 (NOIP1998tg)设有n个正整数,将他们连接成一排,组成一个最大的多位整数。例如:n=3时,3个整数13,312,343,连成的最大整数为:34331213

又如:n=4时,4个整数7,13,4,246连接成的最大整数为7424613

输入:N

N个数

输出:连接成的多位数

算法分析:此题很容易想到使用贪心法,在考试时有很多同学把整数按从大到小的顺序连接起来,测试题目的例子也都符合,但最后测试的结果却不全对。按这种贪心标准,我们很容易找到反例:12,121 应该组成12121而非12112,那么是不是相互包含的时候就从小到大呢?也不一定,如:12,123 就是12312而非12112,这样情况就有很多种了。是不是此题不能用贪心法呢?

其实此题是可以用贪心法来求解,只是刚才的贪心标准不对,正确的贪心标准是:先把整数化成字符串,然后再比较a+b和b+a,如果a+b>b+a,就把a排在b的前面,反之则把a排在b的后面。

源程序:

var

s:array[1..20] of string;

t:string;i,j,k,n:longint;

begin

readln(n);

for i:=1 to n do begin

read(k);

str(k,s[i]);

end;

for i:=1 to n-1 do

for j:=i+1 to n do

if s[i]+s[j]

begin{交换}

t:=s[i];

s[i]:=s[j];

s[j]:=t;

end;

for i:=1 to n do write(s[i]);

end.

贪心算法所作的选择可以依赖于以往所作过的选择,但决不依赖于将来的选择,也不依赖于子问题的解,因此贪心算法与其它算法相比具有一定的速度优势。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。

贪心算法经典例子(2009-07-15 10:17:04)

标签:贪心算法背包问题it分类:简单算法

一、定义

什么是贪心算法呢?所谓贪心算法是指,在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优解出发来考虑,它所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题都能产生整体最优解或整体最优解的近似解。

贪心算法的基本思路如下:

1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每个子问题求解,得到每个子问题的局部最优解。

4.把每个子问题的局部最优解合成为原来问题的一个解。

实现该算法的过程:

从问题的某一初始状态出发;

while 能朝给定总目标前进一步 do

求出可行解的一个解元素;

由所有解元素组合成问题的一个可行解;

二、例题分析

[背包问题]有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。

要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。

物品 A B C D E F G

重量 35 30 60 50 40 10 25

价值 10 40 30 50 35 40 30

记得当时学算法的时候,就是这个例子,可以说很经典。

分析:

目标函数:∑pi最大

约束条件是装入的物品总重量不超过背包容量,即∑wi<=M( M=150)

(1)根据贪心的策略,每次挑选价值最大的物品装入背包,得到的结果是否最优?

(2)每次挑选所占重量最小的物品装入是否能得到最优解?

(3)每次选取单位重量价值最大的物品,成为解本题的策略?

贪心算法是很常见的算法之一,这是由于它简单易行,构造贪心策略简单。但是,它需要证明后才能真正运用到题目的算法中。一般来说,贪心算法的证明围绕着整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。

对于本例题中的3种贪心策略,都无法成立,即无法被证明,解释如下:

(1)贪心策略:选取价值最大者。反例:

W=30

物品:A B C

重量:28 12 12

价值:30 20 20

根据策略,首先选取物品A,接下来就无法再选取了,可是,选取B、C则更好。

(2)贪心策略:选取重量最小。它的反例与第一种策略的反例差不多。

(3)贪心策略:选取单位重量价值最大的物品。反例:

W=30

物品:A B C

重量:28 20 10

价值:28 20 10

根据策略,三种物品单位重量价值一样,程序无法依据现有策略作出判断,如果选择A,则答案错误。

值得注意的是,贪心算法并不是完全不可以使用,贪心策略一旦经过证明成立后,它就是一种高效的算法。比如,求最小生成树的Prim算法和Kruskal算法都是漂亮的贪心算法。

[均分纸牌]有N堆纸牌,编号分别为1,2,…,n。每堆上有若干张,但纸牌总数必为n的倍数.可以在任一堆上取若干张纸牌,然后移动。移牌的规则为:在编号为1上取的纸牌,只能移到编号为2的堆上;在编号为n的堆上取的纸牌,只能移到编号为n-1的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如:n=4,4堆纸牌分别为:① 9 ② 8 ③ 17 ④ 6 移动三次可以达到目的:从③取4张牌放到④再从③区3张放到②然后从②去1张放到①。

输入输出样例:4

9 8 17 6

屏幕显示:3

算法分析:设a[i]为第I堆纸牌的张数(0<=I<=n),v为均分后每堆纸牌的张数,s 为最小移动次数。

我们用贪心算法,按照从左到右的顺序移动纸牌。如第I堆的纸牌数不等于平均值,则移动一次(即s加1),分两种情况移动:

1.若a[i]>v,则将a[i]-v张从第I堆移动到第I+1堆;

2.若a[i]

为了设计的方便,我们把这两种情况统一看作是将a[i]-v从第I堆移动到第I+1堆,移动后有a[i]=v; a[I+1]=a[I+1]+a[i]-v.

在从第I+1堆取出纸牌补充第I堆的过程中可能回出现第I+1堆的纸牌小于零的情况。

如n=3,三堆指派数为1 2 27 ,这时v=10,为了使第一堆为10,要从第二堆移9张到第一堆,而第二堆只有2张可以移,这是不是意味着刚才使用贪心法是错误的呢?

我们继续按规则分析移牌过程,从第二堆移出9张到第一堆后,第一堆有10张,第二堆剩下-7张,在从第三堆移动17张到第二堆,刚好三堆纸牌都是10,最后结果是对的,我们在移动过程中,只是改变了移动的顺序,而移动次数不便,因此此题使用贪心法可行的。

Java源程序:

public class Greedy {

public static void main(String[] args) {

int n = 0, avg =0, s = 0;

Scanner scanner = new Scanner(System.in);

ArrayList array = new ArrayList();

System.out.println("Please input the number of heaps:");

n = scanner.nextInt();

System.out.println("Please input heap number:");

for (int i = 0; i < n; i++) {

array.add(scanner.nextInt());

}

for(int i = 0; i < array.size(); i ++){

avg += array.get(i);

}

avg = avg/array.size();

System.out.println(array.size());

System.out.println(avg);

for(int i = 0; i < array.size()-1; i ++){

s++;

array.set(i+1, array.get(i+1)+array.get(i)-avg);

}

System.out.println("s:" + s);

}

}

利用贪心算法解题,需要解决两个问题:

一是问题是否适合用贪心法求解。我们看一个找币的例子,如果一个货币系统有三种币值,面值分别为一角、五分和一分,求最小找币数时,可以用贪心法求解;如果将这三种币值改为一角一分、五分和一分,就不能使用贪心法求解。用贪心法解题很方便,但它的适用范围很小,判断一个问题是否适合用贪心法求解,目前还没有一个通用的方法,在信息学竞赛中,需要凭个人的经验来判断。

二是确定了可以用贪心算法之后,如何选择一个贪心标准,才能保证得到问题的最优解。在选择贪心标准时,我们要对所选的贪心标准进行验证才能使用,不要被表面上看似正确的贪心标准所迷惑,如下面的例子。

[最大整数]设有n个正整数,将它们连接成一排,组成一个最大的多位整数。

例如:n=3时,3个整数13,312,343,连成的最大整数为34331213。

又如:n=4时,4个整数7,13,4,246,连成的最大整数为7424613。

输入:n

N个数

输出:连成的多位数

算法分析:此题很容易想到使用贪心法,在考试时有很多同学把整数按从大到小的顺序连接起来,测试题目的例子也都符合,但最后测试的结果却不全对。按这种标准,我们很容易找到反例:12,121应该组成12121而非12112,那么是不是相互包含的时候就从小到大呢?也不一定,如12,123就是12312而非12123,这种情况就有很多种了。是不是此题不能用贪心法呢?

其实此题可以用贪心法来求解,只是刚才的标准不对,正确的标准是:先把整数转换成字符串,然后在比较a+b和b+a,如果a+b>=b+a,就把a排在b的前面,反之则把a排在b的后面。

java源程序:

public static void main(String[] args){

String str = "";

ArrayList array = new ArrayList();

Scanner in = new Scanner(System.in);

System.out.println("Please input the number of data:");

int n = in.nextInt();

System.out.println("Please input the data:");

while (n-- > 0) {

array.add(in.next());

}

for(int i = 0; i < array.size(); i ++)

for(int j = i + 1; j < array.size(); j ++){

if((array.get(i) + array.get(j)).compareTo(array.get(j) + array.get(i)) < 0){ String temp = array.get(i);

array.set(i, array.get(j));

array.set(j, temp);

}

}

for(int i = 0; i < array.size(); i ++){

str += array.get(i);

}

System.out.println("str=:"+str);

}

}

贪心算法所作的选择可以依赖于以往所作过的选择,但决不依赖于将来的选择,也不依赖于子问题的解,因此贪心算法与其他算法相比具有一定的速度优势。如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。

贪心算法实例:找零钱(Java实现)收藏

/**********从桌面txt文件里读取零钱数目以及需要找的钱总额然后利用贪心算法求解之后重新生成txt文件******************************************************************

import java.io.*;

public class GreedySelect

{

public GreedySelect( String file)throws IOException

{

try

{

this.file=file;

FileReader reader=new FileReader(file);

BufferedReader Breader=new BufferedReader(reader);

String s=Breader.readLine();

int i,j;

change=new Change[10];

int k=0;

while(s!=null)

{

j=0;

i=0;

String[] temp=new String[9];

temp=s.split("\\s");

change[k]=new Change();

while(i<6)

{

int num=Integer.parseInt(temp[i]);

if(num==0) j++;

change[k].coins[i]=num;

i++;

}

if(j==5) break;

double money=Double.parseDouble(temp[i])*100;

change[k].money=(int)money;

k++;

s=Breader.readLine();

}

client=k-1;

Breader.close();

}

catch(IOException e )

{

e.printStackTrace();

}

}

public void greedySort()//核心代码,贪心求解

{

double money;

double temp=0;

{

System.out.println(change[i]);

money=change[i].money;

for(int j=5;j>=0;j--)

{

if(j==5) temp=200;

else if(j==4) temp=100;

else if(j==3) temp=50;

else if(j==2) temp=20;

else if(j==1) temp=10;

else if(j==0) temp=5;

if(money>=temp&&change[i].coins[j]>0)

{

money-=temp;

change[i].needCoins[j]++;

change[i].coins[j]--;

if(money>=temp&&change[i].coins[j]>0)

j++;

}

}

if(money!=0) change[i].successful=false;

else change[i].successful=true;

}

}

public void saveResult()throws IOException//保存解决方案文件到桌面

{

try

{

FileWriter fileW=new FileWriter("C:\\Documents and Settings\\Administrator\\桌面\ \solution.txt");

PrintWriter writer=new PrintWriter(fileW);

for(int i=0;i

{

if(change[i].successful)

{

writer.println("顾客"+i+" 需要"+change[i].money+"找零钱如下:");

{

int k=change[i].needCoins[j];

if(k>0)

if(j==0) writer.println("五分: "+k);

else if(j==1) writer.println("一角: "+k);

else if(j==2) writer.println("两角: "+k);

else if(j==3) writer.println("五角: "+k);

else if(j==4) writer.println("一元:"+k);

else if(j==5) writer.println("一元:"+k);

}

}

else

{

writer.println("顾客"+i+"无法完成");

}

}

writer.close();

}

catch(IOException e)

{

e.printStackTrace();

}

}

private int client;

private Change[] change;

private String file;

private class Change

{

public Change()//定义顾客问题类

{

coins=new int[6];

needCoins=new int[6];

successful=false;

money=0;

}

public int[] coins;

public int[] needCoins;

public int money;

public boolean successful;

}

}

(一)问题描述

一辆汽车加满油后可以行驶N千米。旅途中有若干个加油站。指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。

给出N,并以数组的形式给出加油站的个数及相邻距离,指出若要使沿途的加油次数最少,设计一个有效的算法,指出应在那些加油站停靠加油。要求:算法执行的速度越快越好。

(二)问题分析(前提行驶前车里加满油)

对于这个问题我们有以下几种情况:设加油次数为k,每个加油站间距离为a[i];i=0,1,2,3……n

1.始点到终点的距离小于N,则加油次数k=0;

2.始点到终点的距离大于N,

A 加油站间的距离相等,即a[i]=a[j]=L=N,则加油次数最少k=n;

B 加油站间的距离相等,即a[i]=a[j]=L>N,则不可能到达终点;

C 加油站间的距离相等,即a[i]=a[j]=L

D 加油站间的距离不相等,即a[i]!=a[j],则加油次数k通过以下算法求解。

(三)算法描述

贪心算法的基本思想

该题目求加油最少次数,即求最优解的问题,可分成几个步骤,一般来说,每个步骤的最优解不一定是整个问题的最优解,然而对于有些问题,局部贪心可以得到全局的最优解。贪心算法将问题的求解过程看作是一系列选择,从问题的某一个初始解出发,向给定目标推进。推进的每一阶段不是依据某一个固定的递推式,而是在每一个阶段都看上去是一个最优的决策(在一定的标准下)。不断地将问题实例归纳为更小的相似的子问题,并期望做出的局部最优的选择产生一个全局得最优解。

贪心算法的适用的问题

贪心算法适用的问题必须满足两个属性:

(1)贪心性质:整体的最优解可通过一系列局部最优解达到,并且每次的选择可以依赖以前做出的选择,但不能依赖于以后的选择。

(2)最优子结构:问题的整体最优解包含着它的子问题的最优解。

贪心算法的基本步骤

(1)分解:将原问题分解为若干相互独立的阶段。

(2)解决:对于每一个阶段求局部的最优解。

(3)合并:将各个阶段的解合并为原问题的解。

[问题分析]

由于汽车是由始向终点方向开的,我们最大的麻烦就是不知道在哪个加油站加油可以使我们既可以到达终点又可以使我们加油次数最少。

提出问题是解决的开始.为了着手解决遇到的困难,取得最优方案。我们可以假设不到万不得已我们不加油,即除非我们油箱里的油不足以开到下一个加油站,我们才加一次油。在局部找到一个最优的解。却每加一次油我们可以看作是一个新的起点,用相同的递归方法进行下去。最终将各个阶段的最优解合并为原问题的解得到我们原问题的求解。

加油站贪心算法设计(C):

include

include

int add(int b[ ],int m,int n)

{ //求一个从m到n的数列的和

int sb;

for(int i=m;i

return sb;

}

int Tanxin(int a[n], int N) //a[n]表示加油站的个数,N为加满油能行驶的最远距离

{

int b[n]; //若在a[i]加油站加油,则b[i]为1,否则为0

int m=0;

if(a[i]>N) return ERROR; //如果某相邻的两个加油站间的距离大于N,则不能到达终点

if(add(a[i], 0, n)

{ //如果这段距离小于N,则不需要加油

b[i]=0;

return add(b[i],0,n);

}

if(a[i]==a[j]&&a[i]==N)

{ //如果每相邻的两个加油站间的距离都是N,则每个加油站都需要加油

b[i]=1;

return add(b[i],0,n);

}

if(a[i]==a[j]&&a[i]

{ //如果每相邻的两个加油站间的距离相等且都小于N

if( add(a[i],m,k) < N && add(a[i],m,k+1) > N )

{

b[k]=1;

m+=k;

}

return add(b[i],0,n);

}

if(a[i]!=a[j])

{ //如果每相邻的两个加油站间的距离不相等且都小于N

if( add(a[i],m,k) < N && add(a[i],m,k+1) > N )

{

b[k]=1;

m+=k;

}

return add(b[i],0,n);

}

viod main( )

{

int a[ ];

scanf("%d",a);

scanf("/n");

scanf("/d",&N);

Tanxin(a[ ],0,n);

}

贪心算法正确性证明:

贪心选择性质

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。对于一个具体的问题,要确定它是否具有贪心性质,我们必须证明每一步所作的贪心选择最终导致问题的一个整体最优解。该题设在加满油后可行驶的N千米这段路程上任取两个加油站A、B,且A距离始点比B距离始点近,则若在B加油不能到达终点那么在A加油一定不能到达终点,因为m+N

最少就会选择距离加满油得点远一些的加油站去加油,因此,加油次数最少满足贪心选择性质。

最优子结构性质:

当一个问题大的最优解包含着它的子问题的最优解时,称该问题具有最优子结构性质。由于(b[1],b[2],……b[n])是这段路程加油次数最少的一个满足贪心选择性质的最优解,则易知若在第一个加油站加油时,b[1]=1,则

(b[2],b[3],……b[n])是从 a[2]到a[n]这段路程上加油次数最少且这段路程上的加油站个数为(a[2],a[3],……a[n])的最优解,即每次汽车中剩下的油不能在行驶到下一个加油站时我们才在这个加油站加一次油,每个过程从加油开始行驶到再次加油满足贪心且每一次加油后相当于与起点具有相同的条件,每个过程都是相同且独立,也就是说加油次数最少具有最优子结构性质。

贪心算法时间复杂度分析

由于若想知道该在哪个加油站加油就必须遍历所有的加油站,且不需要重复遍历,所以时间复杂度为O(n)。

算法设计与分析实验报告贪心算法

算法设计与分析实验报告 贪心算法 班级:2013156 学号:201315614 姓名:张春阳哈夫曼编码 代码 #include float small1,small2; int flag1,flag2,count; typedefstructHuffmanTree { float weight; intlchild,rchild,parent; }huffman; huffmanhuffmantree[100]; void CreatHuffmanTree(intn,int m) { inti; void select(); printf("请输入%d个节点的权值:",n); for(i=0;i

printf("\n"); for(i=0;i

贪心算法经典例题

贪心算法经典例题 发布日期: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)

实验二 贪心算法的应用

实验二贪心算法的应用 一、实验目的 1.掌握贪心算法的基本概念和两个基本要素 2.熟练掌握贪心算法解决问题的基本步骤。 3.学会利用贪心算法解决实际问题。 二、实验内容 1.问题描述: 题目二:会场安排问题 假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法来进行安排。试编程实现对于给定的k个待安排活动,计算使用的最少会场。输入数据中,第一行是k的值,接下来的k行中,每行有2个正整数,分别表示k个待安排活动的开始时间和结束时间,时间以0点开始的分钟计。输出为最少的会场数。 输入数据示例 5 1 23 12 28 25 35 27 80 36 50 输出数据 3 三、算法分析 Stept1:输入各个活动的开始时间(s)和结束时间(e),初始化各活动的会场号。Step2:按活动的开始时间和活动时间排序,s最早(第一优先级)和持续时间最短(第二优先级)的活动排在最前。 Step3:执行贪婪算法,即s最早和持续时间最短的优先安排会场,并记录会场号,其余活动的s大于或等于已安排活动的e的安排在同一会场,若某活动的s

小于安排活动的e,则安排在另一会场,记录会场号,依次循环,直到所有活动均被安排。 Step4:统计会场号数,输出。 时间复杂度:O(n) 算法时间:O(nlogn) 核心算法: void swap(Active &a,Active&b) { Active t; t=a; a=b; b=t; } //活动时间排序 for(i=1;i<=k;i++) { for(j=i;j<=k;j++) { if(a[i].s>a[j].s) swap(a[i],a[j]); if(a[i].s==a[j].s) { if(a[i].e>a[j].e) swap(a[i],a[j]); } } } 四、程序调试及运行结果分析 五、源代码

贪心算法详解分析

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

贪心算法的应用

从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例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]

背包问题的贪心算法

贪心方法:总是对当前的问题作最好的选择,也就是局部寻优。最后得到整体最优。 应用:1:该问题可以通过“局部寻优”逐步过渡到“整体最优”。贪心选择性质与“动态规划”的主要差别。 2:最优子结构性质:某个问题的整体最优解包含了“子”问题的最优解。 代码如下: #include struct goodinfo { float p; //物品效益 float w; //物品重量 float X; //物品该放的数量 int flag; //物品编号 };//物品信息结构体 void Insertionsort(goodinfo goods[],int n) { int j,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].p>goods[i].p) { goods[i+1]=goods[i]; i--; } goods[i+1]=goods[0]; } }//按物品效益,重量比值做升序排列 void bag(goodinfo goods[],float M,int n) { float cu;

for(i=1;i<=n;i++) goods[i].X=0; cu=M; //背包剩余容量 for(i=1;icu)//当该物品重量大与剩余容量跳出 break; goods[i].X=1; cu=cu-goods[i].w;//确定背包新的剩余容量 } if(i<=n) goods[i].X=cu/goods[i].w;//该物品所要放的量 /*按物品编号做降序排列*/ for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].flag

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

武汉理工大学 算法设计与分析论文题目:贪心算法应用研究 姓名:吴兵 学院:信息工程 专业班级:电子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)

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

基于贪心算法与最短路径的基因组组装最优拼接问题---1411

基于贪心算法与最小路径的基因组组装优化问题 摘要 随着人类基因组计划的实施和飞速发展,基因组测序拼接作为生物信息学的核有着极其重要的应用价值。新的测序技术大量涌现,产生的reads 长度更短,数量更多,覆盖率更大,能直接读取的碱基对序列长度远小于基因组长度。本文通过如何在保证组装序列的连续性、完整性和准确性的同时设计耗时短、内存小的组装算法,建立数学模型来解决基因组组装问题。 针对问题一,首先,利用相应的软件对原基因组G 进行切割,利用全基因鸟枪法测序对切割后的短基因进行测序,得到较小的基因组j i G ,通过对比多条任意切割后相似的基因组j i G 从而找出个别碱基对存在的识别错误。而对于基因组中存在的重复片段可以通过两个read 之间的DNA 片段的长度满足一定的分布规律即pared end read 来解决。 接下来对比任意两个11 1m n read 和3 2 2 m n read 是否相等,通过MATLAB 软件建立n m 阶的关联矩阵,最后利用图论中的最短路径方法使更多的基因组能拼接在一起,尽可能使拼接出来的基因组在原基因组的覆盖率达到最大。 针对问题二,先把附件给出的数据提取出来导入MATLAB 中,再结合问题一给出的模型对基因组进行重组,从而得到新的基因。 最后,基于对基因组组装的研究,为使重组基因能更接近原基因序列,对问题一提出模型进行合理性的评价。 关键词:基因组组装 全基因鸟枪法测序 贪心算法 最短路径

一、问题的重述 1.1问题背景 快速和准确地获取生物体的遗传信息对于生命科学研究具有重要的意义。对每个生物体来说,基因组包含了整个生物体的遗传信息,这些信息通常由组成基因组的DNA或RNA分子中碱基对的排列顺序所决定。获得目标生物基因组的序列信息,进而比较全面地揭示基因组的复杂性和多样性,成为生命科学领域的重要研究内容。 1.2问题提出 确定基因组碱基对序列的过程称为测序(sequencing)。测序技术始于20世纪70年代,伴随着人类基因组计划的实施而突飞猛进。从第一代到现在普遍应用的第二代,以及近年来正在兴起的第三代,测序技术正向着高通量、低成本的方向发展。尽管如此,目前能直接读取的碱基对序列长度远小于基因组序列长度,因此需要利用一定的方法将测序得到的短片段序列组装成更长的序列。通常的做法是,将基因组复制若干份,无规律地分断成短片段后进行测序,然后寻找测得的不同短片段序列之间的重合部分,并利用这些信息进行组装。例如,若有两个短片段序列分别为 ATACCTT GCTAGCGT GCTAGCGT AGGTCTGA 则有可能基因组序列中包含有ATACCTT GCTAGCGT AGGTCTGA这一段。当然,由于技术的限制和实际情况的复杂性,最终组装得到的序列与真实基因组序列之间仍可能存在差异,甚至只能得到若干条无法进一步连接起来的序列。对组装效果的评价主要依据组装序列的连续性、完整性和准确性。连续性要求组装得到的(多条)序列长度尽可能长;完整性要求组装序列的总长度占基因组序列长度的比例尽可能大;准确性要求组装序列与真实序列尽可能符合。 利用现有的测序技术,可按一定的测序策略获得长度约为50–100个碱基对的序列,称为读长(reads)。基因组复制份数约为50–100。基因组组装软件可根据得到的所有读长组装成基因组,这些软件的核心是某个组装算法。常用的组装算法主要基于OLC(Overlap/Layout/Consensus)方法、贪婪图方法、de Bruijn 图方法等。一个好的算法应具备组装效果好、时间短、内存小等特点。新一代测序技术在高通量、低成本的同时也带来了错误率略有增加、读长较短等缺点,现有算法的性能还有较大的改善空间。 具体解决问题如下: 问题一:试建立数学模型,设计算法并编制程序,将读长序列组装成基因组。你的算法和程序应能较好地解决测序中可能出现的个别碱基对识别错误、基因组中存在重复片段等复杂情况。 问题二:现有一个全长约为120,000个碱基对的细菌人工染色体(BAC),采用Hiseq2000测序仪进行测序,测序策略以及数据格式的简要说明见附录一和附录二,测得的读长数据见附录三,测序深度(sequencing depth)约为70×,即基因组每个位置平均被测到约70次。试利用你的算法和程序进行组装,并使之具有良好的组装效果。

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

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

贪心算法的应用实例

贪心算法的应用实例 例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,

基于贪心算法的在线形成性考核系统组卷研究

摘要:作业和测试的自动组卷是在线形成性考核系统的核心内容。本文在深入研究贪心算法的基础上,提出了基于贪心算法的自动组卷算法,分析了题库和作业库的约束条件,实现了快速高效的组卷过程。最后给出具体实例加以论证。该算法已经成功应用于实际的在线形成性考核系统中。 关键词:贪心算法;在线形成性考核;约束条件;组卷 一、引言目前,常用的自动组卷算法有随机选取算法、回溯试探算法、蛮力法和遗传算法等,这些算法对在线考试系统确实具有一定的应用价值,但这些方法生成的作业卷和测试卷在试卷的科学性和合理性上考虑较少。在综合研究以上各种算法的优缺点后,保证达到较好时间效率和空间效率的基础上,采用贪心算法为核心和随机选取算法为辅助的组卷算法,应用于在线形成性考核系统在线作业和在线测试中,能够达到较好的组卷效果,并且达到教学辅助效果。决定组卷效率和作业卷质量的主要因素有两个:一是题库和作业库的结构;二是组卷算法的设计。二、贪心算法简介贪心算法建议通过一系列步骤来构造问题的解,每一步对目前构造的部分解做一个扩展,直到获得问题的完整解为止。在每一步中,它要求“贪婪”地选择最佳操作,并希望通过一系列局部的最优选择,能够产生一个全局的最优解。贪心算法一般可以快速得到满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法的基本要素。一是贪心选择性质。所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素。贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题。对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。二是最优子结构性质。当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用贪心算法求解的关键特征。在题库组卷问题中,其最优子结构性质表现为:若a是对于e的题库组卷问题包含试题1的一个最优解,则相容作业卷集合a′= a-{1}是对于e′= {i∈e:si≥f1}的题库组卷问题的一个最优解。三、基于贪心算法的在线形成性考核系统组卷算法1、在线形成性考核系统结构在线形成性考核是指对学生学习过程的测评,是对学生课程学习的阶段性考核,是加强教学过程管理、检验学习效果的重要措施。在该系统中,管理员模块主要负责数据导入导出和系统维护,按照学生的课程注册信息绑定学生的班级、课程、辅导教师及恢复误删除成绩;教师模块完成课程形成性考核方案设计,作业题设计,查询考核内容,作业管理,作业批阅,查询批阅结果,删除已批阅但学生要求重做的作业成绩,学生信息管理,查询作业完成情况,到课率录入;学生模块主要功能是查看形考方案、主持教师、辅导教师、导学教师,在线作业,在线测试,作业成绩及反馈查询。在线形成性考核系统结构如图1所示。图1 在线形成性考核系统结构2、题库设计首先需要确定的是试题组织的方式。为了保证达标原则、全面性原则和主要性原则,最好将试题库与具体的知识内容进行关联,也即以课程知识点为核心组织试题库。然后就要考虑试题本身固有的特性参数,主要有题型、试题内容、答案、难度系数等。难度系数是试题难易程度的指标,也是试卷生成中的一个重要参数,它可以由教师录入试题时给定,并且在同一门课程中要坚持相同的标准,并且难度标准初始设定时要充分考虑到所要测试学生的程度范围。难度系数一般用等级来表示, 在五级难度系数中, 一级难度为最低, 五级难度为最高。题型分为客观题和主观题。客观题分单项选择题、多项选择选、判断题和填空题,主观题分计算题、简答题和论述题。3、作业库设计组卷方式可以按需求由主持老师进行客观题和主观题自由组卷。客观题在学生完成并提交成功后,系统自动阅卷并给出成绩。主观题在学生完成并提交后,由辅导老师阅

贪婪算法

答:贪婪算法(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可匹配(可形成一个匹配对)。在一

c应用贪心算法求解背包问题

实验五应用贪心算法求解背包问题 学院:计算机科学与技术专业:计算机科学与技术 学号:班级:姓名: 、 实验内容: 背包问题指的是:有一个承重为W的背包和n个物品,它们各自的重量和价值分别是n ,假设W w i和v i(1 i n)w i 1i,求这些物品中最有价值的一个子集。如果每次选择某一个物品的时候,只能全部拿走,则这一问题称为离散(0-1)背包问题;如果每次可以拿走某一物品的任意一部分,则这一问题称为连续背包问题。 二、算法思想: 首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。 三、实验过程: #in elude using n amespace std; struct goodi nfo

{ float p; // 物品效益 float w; // 物品重量 float X; // 物品该放的数量 int flag; // 物品编号 };// 物品信息结构体 void Insertionsort(goodinfo goods[],int n)// 插入排序,按pi/wi 价值收益进行排序,一般教材上按冒泡排序 { int j,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].p>goods[i].p) { } goods[i+1]=goods[0]; } }// 按物品效益,重量比值做升序排列goods[i+1]=goods[i]; i--; void bag(goodinfo goods[],float M,int n) { float cu; int i,j;

基于贪心算法的0_1背包问题

Computer Knowledge and Technology 电脑知识与技术软件设计开发本栏目责任编辑:谢媛媛第6卷第35期(2010年12月)基于贪心算法的0-1背包问题 陈曦 (九江学院,江西九江332005) 摘要:贪心算法是解决问题的一种算法,因其解决问题时具有简单性、直观性和高效性而备受青睐。当待解决的问题具有最优子结构和贪心选择性质时,就可以考虑用贪心算法求解。0-1背包问题是计算机问题中一个普遍的问题,文章中详述了用贪心算法如何解决0-1背包问题。并得出用贪心算法求解此问题能得到最优解。 关键词:0-1背包;贪心算法;动态规划中图分类号:TP312文献标识码:A 文章编号:1009-3044(2010)35-10061-02 Based on the Greedy Algorithm of 0-1Knapsack Problems CHEN Xi (Jiujiang University,Jiujiang 332005,China) Abstract:The greedy algorithm is the solution to the problem of an algorithm,because of its solving problems with simplicity,intuitive and the efficiency is favour.When un-solved problems that have the most YouZi structure and moment-the greedy-choice properties,can con -sider to use greedy algorithm.0-1knapsack problems in computer problems is a common problem in the text,was described by the greedy algorithm to solve 0-1knapsack problems.And obtained by greedy algorithm for solving this problem can obtain optimal solutions.Key words:0-1knapsack;greedy algorithm;dynamic programming 1算法设计与分析是一门集应用性、创造性、实践性为一体的综合性极强的课程[1-2] 一个高效的程序不仅需要“编程技巧”,更需要合理的数据组织和清晰高效的算法。当一个问题具有最优子结构时,根据其具体情况可以用动态规划算法或者贪心算法来求解,但是问题同时具有贪心选择性质时,选择贪心算法更优,贪心算法通常会给出一个简单、直观和高效的解法[3]。 贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,它所做出的仅是在某种意义上的局部最优解。贪心算法并不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题它能产生整体最优解或者是整体最优解的近似解。 作为一种算法设计技术,贪心法是一种简单的方法。与动态规划法一样,贪心法也经常用于解决最优化问题。不过与动态规划法不同的是,贪心法在解决问题的策略上是仅根据当前已有的信息做出选择,而且一旦做出了选择,不管将来有什么结果,这个选择都不会改变。这种局部最优选择并不能保证总能获得全局最优解,但是通常能得到较好的近似最优解。例如,平时购物找钱时,为使找回的零钱的硬币数量最少,从最大面值的币种开始,按递减的顺考虑各币种,先尽量用大面值的币种,当不足大面值币种的金额时才去考虑下一种较小的面值的币种。这就是在采用贪心算法。这种方法在这里总是最优,因为银行对其发行的硬币种类和硬币面值的巧妙安排。如果只有面值分别为1,5,和11单位的硬币,而希望找回总额为15单位的硬币,按贪心算法,应找1个11单位面值的硬币和4个1单位面值的硬币,共找回5个硬币,但是最优的解答应是3个5单位面值的硬币。 1.1贪心算法解题思路 贪心算法[4]是经常用到的一种解题方法,往往在解决最优问题时都可以用贪心算法求解。其解题思路为: 1)建立数学模型来描述问题。 2)把求解的问题分成若干子问题。 3)对每一对问题求解,得到子问题的局部最优解。 4)把子问题的解局部最优解合成原来解问题的一个解。 实现该算法的过程: 从问题的某一初始解出发; while 能朝给定总目标前进do 求出可行解的一个元素; 由所有解元素组合成问题的一个可行解。 虽然贪心算法有时并不能得到最优解,但是经过证明贪心算法能提高问题的解决效率。 收稿日期:2010-10-15 作者简介:陈曦(1982-),女,江西九江人,讲师,硕士,主要研究方向为计算机应用。 E-mail:xsjl@https://www.360docs.net/doc/91893298.html, https://www.360docs.net/doc/91893298.html, Tel:+86-551-56909635690964ISSN 1009-3044Computer Knowledge and Technology 电脑知识 与技术Vol.6,No.35,December 2010,pp.10061-1006210061

相关文档
最新文档