pascal搜索回溯.docx
- 文档编号:11535282
- 上传时间:2023-03-19
- 格式:DOCX
- 页数:16
- 大小:25.79KB
pascal搜索回溯.docx
《pascal搜索回溯.docx》由会员分享,可在线阅读,更多相关《pascal搜索回溯.docx(16页珍藏版)》请在冰豆网上搜索。
pascal搜索回溯
【题目】求集合元素问题(1,2x+1,3X+1类)
某集合A中的元素有以下特征:
(1)数1是A中的元素
(2)如果X是A中的元素,则2x+1,3x+1也是A中的元素
(3)除了条件
(1),
(2)以外的所有元素均不是A中的元素
[参考程序1]
usescrt,dos;
vara:
array[1..10000]oflongint;
b:
array[1..10000]ofboolean;
times,n,m,long,i:
longint;
hour1,minute1,second1,sec1001:
word;
hour2,minute2,second2,sec1002:
word;
begin
write('N=');readln(n);
{gettime(hour1,minute1,second1,sec1001);
times:
=minute1*60+second1;
writeln(minute1,':
',second1);}
fillchar(b,sizeof(b),0);
a[1]:
=1;m:
=2;long:
=1;
whilelong<=ndobegin
fori:
=1tolongdo
if(a[i]*2=m-1)or(a[i]*3=m-1)then
ifnotb[m]thenbegin
inc(long);a[long]:
=m;b[m]:
=true;break;
end;
inc(m);
end;
{gettime(hour2,minute2,second2,sec1002);
times:
=minute2*60+second2-times;
writeln(minute2,':
',second2);
writeln('Ok!
UsesTime:
',times);}
fori:
=1tondowrite(a[i],'');
readln;
end.
[参考程序2]
usescrt;
constn=10000;
vara:
array[1..n]oflongint;
i,j,k,l,y:
longint;
begin
clrscr;
fillchar(a,sizeof(a),0);
i:
=1;j:
=1;
a[i]:
=1;
repeat
y:
=2*a[i]+1;
k:
=j;
whiley〈a[k]dobegin
a[k+1]:
=a[k];
k:
=k-1;
end;
ify>a[k]thenbegin
a[k+1]:
=y;j:
=j+1;
end
elseforl:
=k+1tojdoa[l]:
=a[l+1];
j:
=j+1;
a[j]:
=3*a[i]+1;
inc(i);
untilk>=n;
fori:
=1tondobegin
write(a[i],'');
if(imod10=0)or(i=n)thenwriteln
end;
end.
[参考程序3]
usescrt;
vara:
array[1..10000]oflongint;
n,i,one,another,long,s,x,y:
longint;
begin
write('n=');readln(n);
a[1]:
=1;long:
=1;one:
=1;another:
=1;
whilelongythenbegins:
=y;inc(another);end
elsebegins:
=x;inc(one);inc(another);end;
inc(long);a[long]:
=s;
end;
fori:
=1tondowrite(a[i],'');
end.
[参考程序4]
varn:
integer;
top,x:
longint;
functioninit(x:
longint):
boolean;
begin
ifx=1theninit:
=true
elseif((x-1)mod2=0)and(init((x-1)div2))
or((x-1)mod3=0)and(init((x-1)div3))then
init:
=true
elseinit:
=false;
end;
begin
write('inputn:
');
readln(n);
x:
=0;
top:
=0;
whiletop x: =x+1; ifinit(x)then top: =top+1; write(x: 8); end; write('outputend.'); readln end. 〖问题描述〗用高精度计算出S=1! +2! +3! +...n! (n<=50) 其中"! "表示阶乘,例如: 5! =5*4*3*2*1 要求: 输入正整数N,输出计算结果S 四、搜索回溯法 搜索回溯法是程序设计中最常用的一种算法,其思想方法是按一定的顺序对每阶段试探所有可能性: 即从初始态出发向前搜索,如果成功则继续,否则回退一步,如此反复直至所有可能都试遍。 在搜索过程中,须作标志以记住已搜索过的步骤,设栈实现回溯。 算法框架 1、初始化 2、进行第一步搜索(试探) 3、判断搜索是否成功,若成功转5;若不成功,则继续 4、进行该步下一种情况搜索,若该步所有可能都搜索完则转8;否则转3 5、当前情况步数等作标志(进栈),并前进一步 6、判断是否搜索到终点,不是则转2;否则继续。 7、打印结果,清除并转4 8、退后一步(回溯) 9、判断是否退回到初始态,不是则转4;是则结果程序 一、素数环把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。 〖算法分析〗从1开始,每个空位有20(19)种可能,只要填进去的数合法: 与前面的数不相同;与左边相邻的数的和是一个素数。 第20个数还要判断和第1个数的和是否素数。 1、数据初始化; 2、递归填数: 判断第J种可能是否合法; A、如果合法: 填数;判断是否到达目标(20个已填完): 是,打印结果;不是,递归填下一个; B、如果不合法: 选择下一种可能; programtt; vara: array[1..20]ofinteger; k: integer; functionpd1(j,i: integer): boolean; begin pd1: =true; fork: =1toi-1do ifa[k]=jthenbeginpd1: =false;exit;end; end; functionpd2(x: integer): boolean; begin pd2: =true; fork: =2totrunc(sqrt(x))do ifxmodk=0thenbeginpd2: =false;exit;end; end; functionpd3(j,i: integer): boolean; begin ifi<20thenpd3: =pd2(j+a[i-1]) elsepd3: =pd2(j+a[i-1])andpd2(j+1); end; procedureprint; begin fork: =1to20dowrite(a[k]: 4); writeln; end; proceduretry(i: integer); varj: integer; begin forj: =2to20do begin ifpd1(j,i)andpd3(j,i)thenbegin a[i]: =j; ifi=20thenbeginprint;halt;end elsetry(i+1); a[i]: =0; end; end; end; begin fork: =1to20doa[k]: =0; a[1]: =1; try (2); end. 二、编写程序走左图所示的迷宫,要求从A走到B,并印出路径,在走迷宫的过程中,若遇到死胡同,退出时即给堵上。 〖算法分析〗: 将每一格对应每一步,每走一步计算相应的坐标值,每一步又按1、2、3、4四个方向进行试探,是否有路,若有路则前进,否则换方向继续试探;若四个方向都不行,则回溯,并将此路堵上。 三、八皇后问题在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相"冲"(在每一横列竖列斜列只有一个皇后)。 〖问题分析〗主要解决以下几个问题: 1、冲突。 包括行、列、两条对角线: (1)列: 规定每一列放一个皇后,不会造成列上的冲突; (2)行: 当第I行摆上皇后,则同一行上不能再放皇后,把I为下标的标记置为被占领状态; (3)对角线: 对角线有两个方向。 在同一对角线上的所有点(设下标为(i,j)),要么(i+j)是常数,要么(i-j)是常数。 因此,当第I个皇后占领了第J列后,要同时把以(i+j)、(i-j)为下标的标记置为被占领状态。 2、数据结构。 (1)解数组A。 A[I]表示第I个皇后放置的列;范围: 1..8 (2)行冲突标记数组B。 B[I]=0表示第I行空闲;B[I]=1表示第I行被占领;范围: 1..8 (3)对角线冲突标记数组C、D。 C[I-J]=0表示第(I-J)条对角线空闲;C[I-J]=1表示第(I-J)条对角线被占领;范围: -7..7 D[I+J]=0表示第(I+J)条对角线空闲;D[I+J]=1表示第(I+J)条对角线被占领;范围: 2..16 〖算法流程〗 1、数据初始化。 2、从n列开始摆放第n个皇后,先测试当前位置(n,m)是否等于0(未被占领): 如果是,摆放第n个皇后,并宣布占领(记得要横列竖列斜列一起来),接着进行递归; 如果不是,测试下一个位置(n,m+1),若当n<=8,m=8时,已经无法摆放时,进行回溯。 3、当n>8时,便一一打印出结果。 皇后N 4 5 6 7 8 9 10 方案数 2 10 4 40 92 352 724 programqueen;{八皇后问题程序} constn=8; vara,b: array[1..n]ofinteger;{数组a存放解: a[i]表示第i个皇后放在第a[i]列;} c: array[1-n,n-1]ofinteger; d: array[2..n+n]ofinteger;{b为行标志,c、d表示对角线标志} k: integer; procedureprint;{打印结果} varj: integer; begin forj: =1tondowrite(a[j]: 4); writeln; end; procedruetry(i: integer);{递归搜索解} varj: integer;{每个皇后的可放置位置。 注意: 一定要在过程中定义;否则当递归时会覆盖掉它的值,不能得到正确结果} begin forj: =1tondo begin if(b[j]=0)and(c[i-j]=0)and (d[i+j]=0)then{检查位置是否合法} begin a[i]: =j;{置第i个皇后的位置是第j行} b[j]: =1; c[i-j]: =1; d[i+j]: =1;{作已摆放标志} ifi b[j]: =0;c[i-j]: =0;d[i+j]: =0;{回溯: 清摆放标志} end; end; end; begin fork: =1tondob[k]: =0;{初始化数据} fork: =1-nton-1doc[k]: =0; fork: =2ton+ndod[k]: =0; try (1); end. 四、〖题目描述〗输入两个数字(i,j),在第一个数字i中间添上若干个加号,使得这个代数式的值等于第二个数字j。 〖问题分析〗这道题采用的算法是剪枝搜索,逐一在第一个数字i各个数字之间添上加号,并计算出当前代数式的值,如果等于第二个数字j,则退出循环,打印结果“YES”;如果不是,则继续循环;当循环结束后,还未能得出第二个数j,则打印结果“NO”。 〖算法流程〗 1、首先将以字符串输入的第一个数字i切成一个数字e段,放进一个数组a[e]里。 2、接着进行循环,逐一在第一个数字i各个数字之间添上加号,由于在各个数字之间添上加号后代数式的值只有两种情况: 大于第二个数字j或小于第二个数字j,所以循环的内容可以如下: (1)以h,i分别作为当前处理的数字的首位在数组里的位置和在当前数字的第i位添加号。 (2)分别以x1,x2存放添加号后加号前的数值以及加号后的数值,x3将赋值为x1+x2,作为当前代数式的值。 当x3>j时,则进行将h赋值为i,将要处理的数字赋值为加号后的数值,并将x3赋值为x3-x2,作为加号前的数值;当x3 3、当h<=0、h>e、i<=0、i>e、x3<>j时,则退出循环并打印结果“no”;当0 〖参考程序〗 programaa; vara,b: text; c: string; d,e,g,h,i,x1,x2,x3,xx: integer; f: array[1..100]ofinteger; procedurebb; begin assign(a,'tjh.dat'); reset(a); readln(a,c,d); close(a); end; procedurecc; begin fore: =1tolength(c)do f[e]: =ord(c[e])-48; x1: =0;x2: =0;x3: =0;xx: =1;h: =1;i: =1; whilex3<>ddo begin forg: =htoidox1: =x1*10+f[g]; forg: =i+1toedox2: =x2*10+f[g]; x3: =x1+x2+x3; ifx3=dthenexit; if(h<0)or(i<0)thenbeginxx: =0;exit;end; ifx3 begin i: =i+1;x3: =x3-x1-x2; ifi=5thenbeginh: =h-1;i: =h+1;x3: =x3-f[i-1];end; x1: =0;x2: =0; end; ifx3>dthen begin h: =h+1;i: =h;x1: =0;x3: =x3-x2;x2: =0; end; end; end; proceduredd; begin assign(b,'tjh.out'); rewrite(b); ifxx=1thenwriteln(b,'yes') elsewriteln(b,'no'); close(b); end; begin bb; cc; dd; end. 〖习题〗 2、骑士游历问题设有一个N*M的棋盘(2≤N≤50,2≤M≤50),如图所示。 在棋盘上任一点有一个中国象棋马,马走的规则: (1)马走日字; (2)马只能向右走;问题: 当N,M输入之后,找出一条从左下角到右上角的路径。 如: 输入N=4,M=4。 输出(1,1)-(2,3)-(4,4),若不存在路径,则输出‘NO’。 3、任何大于1的自然数N都可以拆分成若干个小于N的自然数之和。 输入N,计算和输出N的不同拆分方案。 4、有一集合,集合中有N个元素,每个元素都是正整数,它们存放在一维数组中,每个数组元素存放一个数,对给定的整数TOTAL(设集合中的每个元素的值都小于TOTAL),求出所有满足下列条件的子集,子集中各元素之和等于TOTAL。 (如设: TOTAL=10,N=7,元素8,4,1,2,5,3,6) 5、有一个由数字1,2,3……,9组成的数字串(长度不超过200),问如何将M(M<=20)个加号("+")插入到这个数字串中,使所形成的算术表达式的值最小.请编一程序解决这个问题. 注意: 加号不能加在数字串的最前面或最末尾,也不应有两个或两个以上的另号相邻.M保证小于数字串的长度. 例如: 数字串798446,若需要加入两个加号,则最佳方案为79+84+46,算术表达式的值为133 程序如下: 程序中T数组用来存放子集 TOTAL=10: N=7 FORI=1TO7: READA(I): NEXT DATA8,4,1,2,5,3,7 S=0: I=0以上初始化 60: I=I+1往前搜索指针I加1 J=J+1: T(J)=I元素编号,送入T数组 S=S+A(I) IFS IFS=TOTALTHEN200 110S=S-A(I): J=J-1回退 120IFI I=T(J)重新设置搜索指针 IFI=NANDJ=1THENEND 150GOTO110 200FORK=1TOJ: PRINTA(T(K));: NEXTK: PRINT: GOTO110 【题目】4×4棋盘上每行每列各摆2颗棋子,要求每一行,每一列上只能放置2个有多少种摆法程序 10DIMa(6),b(6) 20FORi=1TO6: READa(i),b(i): NEXTi 30DATA1,2,1,3,1,4,2,3,2,4,3,4 40i=0 50i=i+1: t(i)=0 60t(i)=t(i)+1 70IFt(i)<=6THEN110 80i=i-1 90IFi<0THENPRINTm: END 100GOTO200 110x=t(i): y(a(x))=y(a(x))+1: y(b(x))=y(b(x))+1 120IFy(a(x))>2ORy(b(x))>2THENGOTO200 130IFi<4THEN50 135m=m+1 140FORj=1TO4: PRINTTAB(a(t(j)));"*";TAB(b(t(j)));"*";: NEXTj 200x=t(i): y(a(x))=y(a(x))-1: y(b(x))=y(b(x))-1: GOTO60 【题目】在4×4的棋盘上放置8个棋,要求每一行,每一列上只能放置2个. 【参考程序1】 算法: 8个棋子,填8次.深度为8.注意判断是否能放棋子时,两个两个为一行. vara: array[1..8]of0..4; line,bz: array[1..4]of0..2;{line数组: 每行已放多少个的计数器} {bz数组: 每列已放多少个的计数器} total: integer; procedureoutput;{输出} vari: integer; begin inc(total);write(total,': '); fori: =1to8dowrite(a[i]);writeln; end; functionok(dep,i: integer): boolean; begin ok: =true; ifdepmod2=0then{假如是某一行的第2个,其位置必定要在第1个之后} if(i<=a[dep-1])thenok: =false; if(bz[i]=2)or(line[depdiv2]=2)thenok: =false; {某行或某列已放满2个} end; procedurefind(dep: integer); vari: integer; begin fori: =1to4dobegin ifok(dep,i)thenbegin a[dep]: =i;{放在dep行i列} inc(bz[i]);{某一列记数器加1} inc(line[depdiv2]);{某一行记数器加1} ifdep=8thenoutputelsefind(dep+1); dec(bz[i]);{回溯} dec(line[depdiv2]); a[dep]: =0; end; end; end; begin total: =0;fillchar(a,sizeof(a),0);fillchar(bz,sizeof(bz),0); find (1); end. 【参考程序2】 算法: 某一行的放法可能性是(1,2格),(1,3格),(1,4格)....共6种放法 const fa: array[1..6]ofarray[1..2]of1..4=((1,2),(1,3),(1,4),(2,3),(2,4),(3,4)); {六种可能放法的行坐标} var a: array[1..8]of0..4; bz: array[1..4]of0..2;{列放了多少个的记数器} total: integer; procedureoutput; vari: integer; begin inc(total); write(total,': '); fori: =1to8dowrite(a[i]); writeln; end; functionok(dep,i: integer): boolean; begin ok: =true;{判断现在的放法中,相应的两列是否已放够2个} if(bz[fa[i,1]]=2)or(bz[fa[i,2]]=2)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- pascal 搜索 回溯