搜索题集.docx
- 文档编号:10549160
- 上传时间:2023-02-21
- 格式:DOCX
- 页数:52
- 大小:32.74KB
搜索题集.docx
《搜索题集.docx》由会员分享,可在线阅读,更多相关《搜索题集.docx(52页珍藏版)》请在冰豆网上搜索。
搜索题集
【题目1】N皇后问题(八皇后问题的扩展)usaco1.5.4
【题目2】排球队员站位问题
【题目3】把自然数N分解为若干个自然数之和。
【题目4】把自然数N分解为若干个自然数之积。
【题目5】马的遍历问题。
【题目6】加法分式分解
【题目7】地图着色问题
【题目8】在n*n的正方形中放置长为2,宽为1的长条块,
【题目9】找迷宫的最短路径。
(广度优先搜索算法)
【题目10】火车调度问题
【题目11】农夫过河
【题目12】七段数码管问题。
【题目13】把1-8这8个数放入下图8个格中,要求相邻的格(横,竖,对角线)上填的数不连续.
【题目14】在4×4的棋盘上放置8个棋,要求每一行,每一列上只能放置2个.
【题目15】迷宫问题.求迷宫的路径.(深度优先搜索法)
【题目16】一笔画问题
【题目17】城市遍历问题.
【题目18】棋子移动问题
【题目19】求集合元素问题(1,2x+1,3X+1类)
【题目1】N皇后问题(含八皇后问题的扩展,规则同八皇后):
在N*N的棋盘上,放置N个皇后,要求每一横行
每一列,每一对角线上均只能放置一个皇后,问可能的方案及方案数。
constmax=8;
vari,j:
integer;
a:
array[1..max]of0..max;{放皇后数组}
b:
array[2..2*max]ofboolean;{/对角线标志数组}
c:
array[-(max-1)..max-1]ofboolean;{\对角线标志数组}
col:
array[1..max]ofboolean;{列标志数组}
total:
integer;{统计总数}
procedureoutput;{输出}
vari:
integer;
begin
write('No.':
4,'[',total+1:
2,']');
fori:
=1tomaxdowrite(a[i]:
3);write('');
if(total+1)mod2=0thenwriteln;inc(total);
end;
functionok(i,dep:
integer):
boolean;{判断第dep行第i列可放否}
begin
ok:
=false;
if(b[i+dep]=true)and(c[dep-i]=true){and(a[dep]=0)}and
(col[i]=true)thenok:
=true
end;
proceduretry(dep:
integer);
vari,j:
integer;
begin
fori:
=1tomaxdo{每一行均有max种放法}
ifok(i,dep)thenbegin
a[dep]:
=i;
b[i+dep]:
=false;{/对角线已放标志}
c[dep-i]:
=false;{\对角线已放标志}
col[i]:
=false;{列已放标志}
ifdep=maxthenoutput
elsetry(dep+1);{递归下一层}
a[dep]:
=0;{取走皇后,回溯}
b[i+dep]:
=true;{恢复标志数组}
c[dep-i]:
=true;
col[i]:
=true;
end;
end;
begin
fori:
=1tomaxdobegina[i]:
=0;col[i]:
=true;end;
fori:
=2to2*maxdob[i]:
=true;
fori:
=-(max-1)tomax-1doc[i]:
=true;
total:
=0;
try
(1);
writeln('total:
',total);
end.
【题目2】排球队员站位问题
四
三
二
五
六
一
上图为排球场的平面图,其中一、二、三、四、五、六为位置编号,二、三、四号位置为前排,一、六、五号位为后排。
某队比赛时,一、四号位放主攻手,二、五号位放二传手,三、六号位放副攻手。
队员所穿球衣分别为1,2,3,4,5,6号,但每个队员的球衣都与他们的站位号不同。
已知1号、6号队员不在后排,2号、3号队员不是二传手,3号、4号队员不在同一排,5号、6号队员不是副攻手。
编程求每个队员的站位情况。
正确解:
正确的站位顺序为:
123456
三六四五一二
【算法分析】本题可用一般的穷举法得出答案。
也可用回溯法。
以下为回溯解法。
【参考程序】
typesset=setof1..6;
vara:
array[1..6]of1..6;
d:
array[1..6]ofsset;
i:
integer;
procedureoutput;{输出}
begin
ifnot((a[3]in[2,3,4])=(a[4]in[2,3,4]))then
begin{3,4号队员不在同一排}
write('number:
');fori:
=1to6dowrite(i:
8);writeln;
write('weizhi:
');fori:
=1to6dowrite(a[i]:
8);writeln;
end;
end;
proceduretry(i:
integer;s:
sset);{递归过程i:
第i个人,s:
哪些位置已安排人了}
var
j,k:
integer;
begin
forj:
=1to6dobegin{每个人都有可能站1-6这6个位置}
if(jind[i])andnot(jins)thenbegin
{j不在d[i]中,则表明第i号人不能站j位.j如在s集合中,表明j位已排人了}
a[i]:
=j;{第i人可以站j位}
ifi<6thentry(i+1,s+[j]){未安排妥,则继续排下去}
elseoutput;{6个人都安排完,则输出}
end;
end;
end;
begin
fori:
=1to6dod[i]:
=[1..6]-[i];{每个人的站位都与球衣的号码不同}
d[1]:
=d[1]-[1,5,6];
d[6]:
=d[6]-[1,5,6];{1,6号队员不在后排}
d[2]:
=d[2]-[2,5];
d[3]:
=d[3]-[2,5];{2,3号队员不是二传手}
d[5]:
=d[5]-[3,6];
d[6]:
=d[6]-[3,6];{5,6号队员不是副攻手}
try(1,[]);
end.
【题目3】把自然数N分解为若干个自然数之和。
【参考答案】
n│total
5│7
6│11
7│15
10│42
100│190569291
【参考程序】
varn:
byte;num:
array[0..255]ofbyte;total:
word;
procedureoutput(dep:
byte);
varj:
byte;
begin
forj:
=1todepdowrite(num[j]:
3);writeln;inc(total);
end;
procedurefind(n,dep:
byte);{N:
待分解的数,DEP:
深度}
vari,j,rest:
byte;
begin
fori:
=1tondo{每一位从N到1去试}
ifnum[dep-1]<=ithen{保证选用的数大于前一位}
begin
num[dep]:
=i;
rest:
=n-i;{剩余的数进行下一次递归调用}
if(rest>0)thenbeginfind(rest,dep+1);end
elseifrest=0thenoutput(dep);{刚好相等则输出}
num[dep]:
=0;
end;
end;
begin{主程序}
writeln('inputn:
');readln(n);
fillchar(num,sizeof(num),0);
total:
=0;num[0]:
=0;
find(n,1);
writeln('sum=',total);
end.
【题目4】把自然数N分解为若干个自然数之积。
【参考程序】
varpath:
array[1..1000]ofinteger;
total,n:
integer;
procedurefind(k,sum,dep:
integer);{K:
}
varb,d:
Integer;
begin
ifsum=nthen{积等于N}
begin
write(n,'=',path[1]);
ford:
=2todep-1dowrite('*',path[d]);
writeln;inc(total);
exit;
end;
ifsum>nthenexit;{累积大于N}
forb:
=trunc(n/sum)+1downtokdo{每一种可能都去试}
begin
path[dep]:
=b;
find(b,sum*b,dep+1);
end;
end;
begin
readln(n);total:
=0;
find(2,1,1);writeln('total:
',total);
readln;
end.
【题目5】马的遍历问题。
在N*M的棋盘中,马只能走日字。
马从位置(x,y)处出发,把
棋盘的每一格都走一次,且只走一次。
找出所有路径。
【参考程序】{深度优先搜索法}
constn=5;m=4;
fx:
array[1..8,1..2]of-2..2=((1,2),(2,1),(2,-1),(1,-2),(-1,-2),(-2,-1),
(-2,1),(-1,2));{八个方向增量}
var
dep,i:
byte;x,y:
byte;
cont:
integer;{统计总数}
a:
array[1..n,1..m]ofbyte;{记录走法数组}
procedureoutput;{输出,并统计总数}
varx,y:
byte;
begin
cont:
=cont+1;writeln;
writeln('count=',cont);
fory:
=1tondobegin
forx:
=1tomdowrite(a[y,x]:
3);writeln;
end;{readln;halt;}
end;
procedurefind(y,x,dep:
byte);
vari,xx,yy:
integer;
begin
fori:
=1to8do
begin
xx:
=x+fx[i,1];yy:
=y+fx[i,2];{加上方向增量,形成新的坐标}
if((xxin[1..m])and(yyin[1..n]))and(a[yy,xx]=0)then
{判断新坐标是否出界,是否已走过?
}
begin
a[yy,xx]:
=dep;{走向新的坐标}
if(dep=n*m)thenoutput
elsefind(yy,xx,dep+1);{从新坐标出发,递归下一层}
a[yy,xx]:
=0{回溯,恢复未走标志}
end;
end;
end;
begin
cont:
=0;
fillchar(a,sizeof(a),0);
dep:
=1;
writeln('inputy,x');readln(y,x);
{x:
=1;y:
=1;}
if(y>n)or(x>m)thenbeginwriteln('x,yerror!
');halt;end;
a[y,x]:
=1;
find(y,x,2);
ifcont=0thenwriteln('Noanswer!
')elsewrite('TheEnd!
');
readln;
end.
【题目6】加法分式分解。
如:
1/2=1/4+1/4.找出所有方案。
输入:
NMN为要分解的分数的分母
M为分解成多少项
【参考程序】
programfenshifenjie;
constnums=5;
var
t,m,dep:
integer;
n,maxold,max,j:
longint;
path:
array[0..nums]oflongint;
maxok,p:
boolean;
sum,sum2:
real;
procedureprint;
vari:
integer;
begin
t:
=t+1;
ifmaxok=truethenbeginmaxold:
=path[m];maxok:
=false;end;
write('NO.',t);
fori:
=1tomdowrite('',path[i]:
4);writeln;
ifpath[1]=path[m]thenbeginwriteln('Ok!
total:
',t:
4);readln;halt;end;
end;
procedureinput;
begin
writeln('inputN:
');readln(n);
writeln('inputM(M<=',nums:
1,'):
');readln(m);
if(n<=0)or(m<=0)or(m>4)or(n>maxlongint)
thenbeginwriteln('InvalidInput!
');readln;halt;end;
end;
functionsum1(ab:
integer):
real;
vara,b,c,d,s1,s2:
real;
i:
integer;
begin
ifab=1then
sum1:
=1/path[1]
else
begin
a:
=path[1];
b:
=1;
c:
=path[2];
d:
=1;
fori:
=1toab-1do
begin
s2:
=(c*b+a*d);
s1:
=(a*c);
a:
=s1;
b:
=s2;
c:
=path[i+2];
end;
sum1:
=s2/s1;
end;
end;
procedureback;
begin
dep:
=dep-1;
ifdep<=m-2thenmax:
=maxold;
sum:
=sum-1/path[dep];
j:
=path[dep];
end;
procedurefind;
begin
repeat
dep:
=dep+1;
j:
=path[dep-1]-1;
p:
=false;
repeat
j:
=j+1;
if(dep<>m)and(j<=max)then
if(sum+1/j)>=1/nthenp:
=false
elsebegin
p:
=true;
path[dep]:
=j;
sum:
=sum+1/path[dep];
end
elseifj>maxthenback;
ifdep=mthenbegin
path[dep]:
=j;
sum2:
=sum1(m);
if(sum2)>1/nthenp:
=false;
if(sum2)=1/nthenbeginprint;
max:
=j;
back;
end;
if(sum2<1/n)thenback;
if(j>=max)thenback;
end;
untilp
untildep=0;
end;
begin
INPUT;
maxok:
=true;
fort:
=0tomdopath[t]:
=n;
dep:
=0;t:
=0;sum:
=0;
max:
=maxlongint;
find;
readln;
end.
【题目7】地图着色问题
【参考程序1】
constlin:
array[1..12,1..12]of0..1{区域相邻数组,1表示相邻}
=((0,1,1,1,1,1,0,0,0,0,0,0),
(1,0,1,0,0,1,1,1,0,0,0,0),
(1,1,0,1,0,0,0,1,1,0,0,0),
(1,0,1,0,1,0,1,0,1,1,0,0),
(1,0,0,1,0,1,0,0,0,1,1,0),
(1,1,0,0,1,0,1,0,0,0,1,0),
(0,1,0,0,0,1,0,1,0,0,1,1),
(0,1,1,0,0,0,1,0,1,0,0,1),
(0,0,1,1,0,0,0,1,0,1,0,1),
(0,0,0,1,1,0,0,0,1,0,1,1),
(0,0,0,0,1,1,1,0,0,1,0,1),
(0,0,0,0,0,0,1,1,1,1,1,1));
varcolor:
array[1..12]ofbyte;{color数组放已填的颜色}
total:
integer;
functionok(dep,i:
byte):
boolean;{判断选用色i是否可用}
vark:
byte;{条件:
相邻的区域颜色不能相同}
begin
fork:
=1todepdo
if(lin[dep,k]=1)and(i=color[k])thenbeginok:
=false;exit;end;
ok:
=true;
end;
procedureoutput;{输出}
vark:
byte;
begin
fork:
=1to12dowrite(color[k],'');writeln;
total:
=total+1;
end;
procedurefind(dep:
byte);{参数dep:
当前正在填的层数}
vari:
byte;
begin
fori:
=1to4dobegin{每个区域都可能是1-4种颜色}
ifok(dep,i)thenbegin
color[dep]:
=i;
ifdep=12thenoutputelsefind(dep+1);
color[dep]:
=0;{恢复初始状态,以便下一次搜索}
end;
end;
end;
begin
total:
=0;{总数初始化}
fillchar(color,sizeof(color),0);
find
(1);
writeln('total:
=',total);
end.
【参考程序2】
const{lin数组:
代表区域相邻情况}
lin:
array[1..12]ofsetof1..12=
([2,3,4,5,6],[1,3,6,7,8],[1,2,4,8,9],[1,3,5,9,10],[1,4,6,10,11],
[1,2,5,7,11],[12,8,11,6,2],[12,9,7,2,3],[12,8,10,3,4],
[12,9,11,4,5],[12,7,10,5,6],[7,8,9,10,11]);
color:
array[1..4]ofchar=('r','y','b','g');
vara:
array[1..12]ofbyte;{因有12个区域,故a数组下标为1-12}
total:
integer;
functionok(dep,i:
integer):
boolean;{判断第dep块区域是否可填第i种色}
varj:
integer;{j为什么设成局部变量?
}
begin
ok:
=true;
forj:
=1to12do
if(jinlin[dep])and(a[j]=i)thenok:
=false;
end;
procedureoutput;{输出过程}
varj:
integer;{j为什么设成局部变量?
}
begin
inc(total);{方案总数加1}
write(total:
4);{输出一种方案}
forj:
=1to12dowrite(color[a[j]]:
2);writeln;
end;
procedurefind(dep:
byte);
vari:
byte;{i为什么设成局部变量?
}
begin
fori:
=1to4do{每一区域均可从4种颜色中选一}
begin
ifok(dep,i)thenbegin{可填该色}
a[dep]:
=i;{第dep块区域填第i种颜色}
if(dep=12)thenoutput{填完12个区域}
elsefind(dep+1);{未填完}
a[dep]:
=0;{取消第dep块区域已填的颜色}
end;
end;
end;
begin{主程序}
fillchar(a,sizeof(a),0);{记得要给变量赋初值!
}
total:
=0;
find
(1);
writeln('End.');
end.
【题目8】在n*n的正方形中放置长为2,宽为1的长条块,问放置方案如何
【参考程序1】
constn=4;
vark,u,v,result:
integer;
a:
array[1..n,1..n]ofchar;
procedureprintf;{输出}
begin
result:
=result+1;{方案总数加1}
writeln('---',result,'---');
forv:
=1tondobegin
foru:
=1tondowrite(a[u,v]);writelnend;writeln;
end;
proceduretry;{填放长条块}
vari,j,x,y:
integer;full:
boolean;
begin
full:
=true;
ifk<>trunc(n*n/2)thenfull:
=false;{测试是否已放满}
iffullthenprintf;{放满则可输出}
ifnotfullthenbegin{未满}
x:
=0;y:
=1;{以下先搜索未放置的第一个空位置}
repeat
x:
=x+1;
ifx>nthenbeginx:
=1;y:
=y+1end
untila[x,y]
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 搜索
![提示](https://static.bdocx.com/images/bang_tan.gif)