基本算法1-枚举法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
我们不可能对14个格子 中的数都进行枚举,本题的 关键在于找出适当的元素进 行枚举。
请根据上述算式中的信息求出被除数和除数。
其它信息: 设除数为x,被除数为y,则10<=x<=99,1000<=y<=9999,且8*x<=99, 9*x>=100。
穷举法是一种比较笨拙的算法,因为它需要列举出许多个可能解来一一验证,程 序往往需要运行很长时间,效率较低。
3. 输入:一个算法有0个或多个输入,以描述运算对象的初始情况,所 谓0个输入是指算法本身定义了初始条件。如在5个数中找出最小的数, 则有5个输入。
4. 输出:一个算法有一个或多个输出,以反映对输入数据加工后的结果, 这是算法设计的目的。它们是同输入有着某种特定关系的量。如上述 在5个数中找出最小的数,它的输出为最小的数。如果一个程序没有 输出,这个程序就毫无意义了;
z div 3=100)and(z mod
3=0)then
writeln('x=',x,'y=',y,'z=',z);
{验证可能的解,并输出符
合题目要求的解}
❖ end.
❖ 改进后:
❖ var x,y,z:integer;
❖ begin
❖ for x:=0 to 33 do
❖ for y:=0 to 50 do
end;
end.
运行结果:
9709 12
❖ 例3、将1,2...9共9 个数分成三组,分
❖ 算法分析:此题数据规模不 大,可以进行枚举,如果我 们不加思地以每一个数位为
别组成三个三位数, 且使这三个三位数 构成1:2:3的比例,
❖ ❖
枚举对象,一位一位地去枚 举: for a:=1 to 9 do for b:=1 to 9 do
const
link:array[1..6,1..2] of integer=((1,2),(1,4),(2,5),(4,7),(5,8),(7,8)); var
b:array[1..8] of integer;{存放摆放方案}
procedure print; {输出一种满足条件的放法} begin writeln(b[1]:4); writeln(b[2]:2,b[3]:2,b[4]:2); writeln(b[5]:2,b[6]:2,b[7]:2); writeln(b[8]:4); writeln; end;
❖ var i,t,n,sum:longint; ❖ begin ❖ t:=0; sum:=1; ❖ readln(n); ❖ for i:=1 to n do ❖ begin
❖ sum:=sum*i;
❖ while sum mod 10=0 do
❖ begin
❖
sum:=sum div 10;
❖
inc(t);{计数器增加1}
试求出所有满足条 ❖ ………
件的三个三位数. ❖ 例如:三个三位数
❖ for i:=1 to 9 do ❖ 这样下去,枚举次数就有9
9次,如果我们分别设三个
192,384,576满足 以上条件.
数为x,2x,3x,以x为枚举对 象,穷举的范围就减少为9 3,在细节上再进一步优化,
枚举范围就更少了。
❖ var ❖ t,x:integer; ❖ s,st:string; ❖ c:char; ❖ begin ❖ for x:=123 to 321 do{枚举
枚举法(穷举法)
在程序设计中,我们经常需要根据给定的一组条件求满足 条件的解。如果问题的解可以用公式,或者按一定的规则、规 律求出,那么就可以很容易地写出相应的程序。但是对于许多 问题,我们都难以找到明确的公式和计算规则,在这种情况下, 我们可以利用计算机高速运算的特点,用穷举法来求解。
基本思想:
所有可能的解} ❖ begin ❖ t:=0; ❖ str(x,st);{把整数x转化为
字符串,存放在st中} ❖ str(x*2,s);
❖ st:=st+s;
❖ str(x*3,s);
❖ st:=st+s; ❖ for c:='1' to '9' do{枚举9个
字符,判断是否都在st中}
❖ if pos(c,st)<>0 then inc(t) else break;{如果不在 st中,则退出循环}
❖ procedure try;
❖ var b2,b4,b5,b7:integer;
❖ begin
❖ for b2:=3 to 6 do {枚举b[2],b[4],b[5],计算 b[7]}
❖ for b4:=3 to 6 do
❖ if b2<>b4 then
❖
Βιβλιοθήκη Baidu
for b5:=3 to 6 do
❖
信息学奥赛中的基本算法
一、枚举法
一、算法相关知识
❖ 从广义上讲,算法是指为解决一个问题而采 用的方法和步骤 。
❖ 从程序计设的角度上讲,算法是指利用程序 设计语言的各种语句,为解决特定的问题而 构成的各种逻辑组合。
❖ 程序设计的实质就是用计算机语言构造解决 问题的算法。算法是程序设计的灵魂 。
算法的基本特征
❖
的个数,因此问题转化 ❖
为直接求n!的分解数 ❖
中含5的个数。
❖
readln(n); t:=0; repeat
n:=n div 5 ; inc(t,n); {计数器增加n} until n<5;
❖ var t,n:integer;
❖ writeln(t:6);
❖ begin
❖ end.
时间复杂度为O(logN)
穷举也叫枚举,它的基本思想是先依据题目的部分条件将 所有可能解列举出来,然后用其余的条件对所有可能解进行一 一验证,删去那些不符合条件的解,剩下符合条件的解就是整 个问题的解。
适用枚举法求解的问题必须满足两个条件:
1、可事先确定解元素的个数n;
2、解变量A1,A2,…,An的可能值为一个连续的值域。
function choose:boolean; {检验当前放法是否符合要求} var i:integer; begin choose:=false; for i:=1 to 6 do if abs( b[link[i,1]] - b[link[i,2]] )=1 then exit; choose:=true; end;
和买鸡用去的钱的总数 (x*3+y*2+z)为判定条件, 穷举各种鸡的个数。
❖ 程序一:
❖ var x,y,z:integer;
❖ begin
❖ for x:=0 to 100 do
❖ for y:=0 to 100 do
❖ for z:=0 to 100 do{枚举 所有可能的解}
❖
if
(x+y+z=100)and(x*3+y*2+
❖ if t=9 then
writeln(x,' ',x*2,' ',x*3);
❖ end;
❖ end.
例4:方格填数
如下图所示的八个格子中填入1至8八个数字,使得相邻的 和对角线的数字之差不为1。请编程找出所有放法。
b1
b2 b3 b4
b5 b6 b7
b8
分析: 由题意可知,放入b3,b6这两个格子中的数,必须和六个数不连续,仅 可以和一个数是连续的,这样的数只能是1和8。因此,b1,b3,b6,b8这四 个格子中数的放法可以先确定下来:2,8,1,7或7,1,8,2。接着,我们 只需枚举b2、b4、b5三个变量,范围都是3至6,而b7可通过计算来得到。 (1,2),(1,4),(2,5),(4,7),(5,8),(7,8)共6对格子中的数需要验证。
❖ 5.for i:=1 to n do begin for j:=1 to n do s[i,j,0]:=0; for j:=1 to n do for k:=1 to n do s[i,j,k]:=1; end;
❖ 执行次数n*(n+n*n)次,时间复杂度O(n^3)
按数量级递增排列,常见的时间复杂度有:
枚举所有可能的除数
for x:=10 to 99 do
begin
y:=( 809*x+1); {计算出被除数}
验证
if y>9999 then break;{优化语句} if ( (y>=1000) and (8*x<=99) and (9*x>=100) )
then writeln(y,' ',x);
❖ 例1:百钱买百鸡问题: 有一个人有一百块钱, 打算买一百只鸡。到市 场一看,大鸡三块钱一 只,小鸡一块钱三只, 不大不小的鸡两块钱一 只。现在,请你编一程 序,帮他计划一下,怎 么样买法,才能刚好用 一百块钱买一百只鸡?
❖ 算法分析:此题很显然
是用枚举法,我们以三
种鸡的个数为枚举对象 (分别设为x,y,z),以三 种鸡的总数(x+y+z)
❖ begin
❖
z:=100-x-y;
❖
if (x*3+y*2+z div
3=100)and(z mod
3=0)then
writeln('x=',x,'y=',y,'z=',z);
❖ end;
❖ end.
例2、猜算式
设有下列的除法算式:
本题已给出了商 和余数,只要再知道 被除数或除数,就可 确定整个算式。枚举 除数枚举量较小,我 们选择枚举除数,而 被除数则可按公式 y=809*x+1计算得出。
5. 可行性: 算法中每一步运算应该是可行的。算法原则上能够精确地运 行,而且人能用笔和纸做有限次运算后即可完成。
如何评价算法的好坏?
❖ 时间复杂度:算法运行所占用的时间 ❖ 空间复杂度:算法运行时所占用的空间 ❖ 信息学奥赛中,对程序的运行时间作出了严
格的限制,如果运行时间超出了限定就会判 错,因此在设计算法时首先要考虑的是时间 因素,必要时可以以牺牲空间来换取时间
❖ end;
❖ sum:=sum mod 1000;{舍去 与生成0无关的数}
❖ end;
❖ writeln(t:6);
❖ end.
时间复杂度为O(N)
例:求N!所产生的数后面有多少个0(中间的0不计)
❖ 算法二:此题中生成0 ❖
的个数只与含5的个数 ❖
有关,n!的分解数中 含5的个数就等于末尾0
for j:=1 to n div 2 do s[i,j]:=0;
执行次数n*n/2次,时间复杂度O(n^2) ❖ 4.for i:=1 to n do
for j:=1 to n-1 do for k:=1 to n-2 do
s[i,j,k]:=0; 执行次数n*(n-1)*(n-2)次,时间复杂度O(n^3)
针对穷举法效率较低的缺点,在设计穷举算法时,我们必须注意以下二点:
①减少枚举变量:充分挖掘各解元素之间的联系,将一些非枚举不可的解元素列 为枚举变量,然后在此基础上直接计算出其它解元素的可能值。
②减少枚举变量的值域:枚举前要尽可能多地将不符合条件的情况预先排除。
var
x,y:integer; begin
时间复杂度怎么算?
❖ 1.for i:=1 to 100 do for j:=1 to 100 do s[i,j]:=0;
执行次数100*100次,时间复杂度O(1) ❖ 2.for i:=1 to n do
for j:=1 to 200 do s[i,j]:=0;
执行次数n*200次,时间复杂度O(n) ❖ 3.for i:=1 to n do
1. 有穷性: 一个算法应包括有限的运算步骤,执行了有穷的操作后将终 止运算,不能是个死循环;
2. 确切性: 算法的每一步骤必须有确切的定义,读者理解时不会产生二 义性。并且,在任何条件下,算法只有唯一的一条执行路径,对于相 同的输入只能得出相同的输出。如在算法中不允许有“计算8/0”或 “将7或8与x相加”之类的运算,因为前者的计算结果是什么不清楚, 而后者对于两种可能的运算应做哪一种也不知道。
if (b5<>b2)and(b5<>b4) then
❖
begin
❖
b7:=18-b2-b4-b5;
❖
b[2]:=b2;b[4]:=b4;b[5]:=b5;b[7]:=b7;
❖
if choose then print;
❖
end;
常数阶O(1) 对数阶O(logn)
线性阶O(n),
线性对数阶O(nlogn)
平方阶O(n^2)
立方阶O(n^3) ... k次方阶O(n^k),
指数阶O(2^n)
用例子说明一下改进算法对降低时间复杂度的好处。
例:求N!所产生的数后面有多少个0(中间的0不计)
❖ 算法一:从1乘到n,每乘一个数 判断一次,若后面有0则去掉后 面的0,并记下0的个数。为了不 超出数的表示范围,去掉与生成 0无关的数,只保留有效位数, 当乘完n次后就得到0的个数。