搜索算法个人总结pascal.docx
《搜索算法个人总结pascal.docx》由会员分享,可在线阅读,更多相关《搜索算法个人总结pascal.docx(34页珍藏版)》请在冰豆网上搜索。
![搜索算法个人总结pascal.docx](https://file1.bdocx.com/fileroot1/2023-1/5/b5864372-7cb3-476b-8b87-95ec473cdfc5/b5864372-7cb3-476b-8b87-95ec473cdfc51.gif)
搜索算法个人总结pascal
2011.10.17总结
(1-5题为今天重写一次,其下所表示的提交次数为今天重写的提交次数,其他题提交次数为原来的次数,部分不详,题号前加星号表示未AC)
1·N皇后(位运算版)
这个是看了标程后写的,很有意思很巧妙的做法,也很强大,一次wa,是因为没写inc(sum),。
①(只输出结果数目)
programquen;
var
k,sum,n:
longint;
proceduredfs(row,l,r:
longint);//row:
列l,r:
两条对角线
var
pos,p:
longint;
begin
ifrow<>kthen
begin
pos:
=kandnot(lorrorrow);//表示需要放皇后的的位子
whilepos<>0do//有皇后要放
begin
p:
=posand(notpos+1);//取最右边的1//p表示某个可以放上皇后的地方
pos:
=pos-p;//放上皇后
dfs(row+p,(l+p)shl1,(r+p)shr1);//回溯,注意对角线的处理
end;
end
elseinc(sum);
end;
begin
readln(n);
k:
=(1shln)-1;//每一位都是1,目标状态
dfs(0,0,0);
writeln(sum);
end.
②(输出前3种方案,tyvj080)
programquen{输出前3种解};
var
k,sum,n,i,t:
longint;
a:
array[0..14]oflongint;
proceduredfs(dep,row,l,r:
longint);//dep:
层数row:
列l,r:
两条对角线
var
pos,p,i:
longint;
begin
ifdep>nthen//决策有效
begin
inc(sum);
ifsum<=3then
begin
fori:
=1tondo
write(a[i],'');//输出决策
writeln;
end;
end
elsebegin
fori:
=1tondo//第i位是否可以放皇后
begin
p:
=(1shl(i-1));//二进制决策
pos:
=pand(roworlorr);//pos记录冲突
if(pos=0)//没有冲突
thenbegin
a[dep]:
=i;//记录决策
dfs(dep+1,row+p,(l+p)shl1,(r+p)shr1);//下一层递归
end;
end;
end
end;
begin
readln(n);
k:
=(1shln)-1;//每一位都是1,目标状态
fori:
=1tondo
begin
a[1]:
=i;//初始化第一行,有n个状态
t:
=1shl(i-1);
dfs(2,t,tshl1,tshr1);
end;
writeln(sum);
end.
2.计算细胞数
一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
如:
阵列
0234500067
1034560500
2045600671
0000000089
有4个细胞
输入格式InputFormat
第一行 :
两个数字MN(1<=M<=501<=N<80)表示该阵列有M行N列
从第2行到第M+1行 每行有连续的N个字符
输出格式OutputFormat
一行:
细胞个数
似乎我写出来的不是标准的搜索……
//思路:
以细胞中的一个点为起点,将他及他周围的不为0的点都改为0,然后找下一个。
//提交情况:
一次AC
programtyvj1127;
var
n,m,re:
longint;
a:
array[1..100,1..100]oflongint;
procedureinit;
begin
assign(input,'tyvj1127.in');
assign(output,'tyvj1127.out');
reset(input);
rewrite(output);
end;
procedurechange(i,j:
longint);
var
k,l:
longint;
begin
a[i,j]:
=0;
ifi>1thenifa[i-1,j]>0thenchange(i-1,j);
ifa[i+1,j]>0thenchange(i+1,j);
ifj>1thenifa[i,j-1]>0thenchange(i,j-1);
ifa[i,j+1]>0thenchange(i,j+1);
end;
procedureprepare;
var
i,j:
longint;
k:
char;
begin
readln(n,m);
fori:
=1tondo
begin
forj:
=1tomdo
begin
read(k);
val(k,a[i,j]);
end;
readln;
end;
re:
=0;
fori:
=1tondo
forj:
=1tomdo
begin
ifa[i,j]<>0thenbeginchange(i,j);re:
=re+1;end;
end;
writeln(re);
end;
procedureoutit;
begin
close(input);
close(output);
end;
begin
init;
prepare;
outit;
end.
3·滑雪
trs喜欢滑雪。
他来到了一个滑雪场,这个滑雪场是一个矩形,为了简便,我们用r行c列的矩阵来表示每块地形。
为了得到更快的速度,滑行的路线必须向下倾斜。
例如样例中的那个矩形,可以从某个点滑向上下左右四个相邻的点之一。
例如24-17-16-1,其实25-24-23…3-2-1更长,事实上这是最长的一条。
输入文件
第1行:
两个数字r,c(1<=r,c<=100),表示矩阵的行列。
第2..r+1行:
每行c个数,表示这个矩阵。
输出文件
仅一行:
输出1个整数,表示可以滑行的最大长度。
样例输入SampleInput
55
12345
161718196
152425207
142322218
131211109
样例输出SampleOutput
25
记忆化搜索,也没设么好说的,就是刚开始的时候写出来总是无法跳出递归……
提交情况:
1次WA 原因:
没删input和output
programski;
const
maxn=100;
dx:
array[1..4]oflongint=(0,-1,0,1);
dy:
array[1..4]oflongint=(1,0,-1,0);
var
a,f:
array[1..maxn,1..maxn]oflongint;
max,r,c,i,j:
longint;
functionbest(x,y:
longint):
longint;
var
i,x2,y2:
longint;
begin
iff[x,y]>0thenexit(f[x,y]);
best:
=1;
fori:
=1to4do
begin
x2:
=x+dx[i];
y2:
=y+dy[i];
if(x2<=r)and(x2>=1)and(y2<=c)and(y2>=1)and(a[x,y]>a[x2,y2])then
begin
ifbest(x2,y2)+1>bestthen
best:
=best(x2,y2)+1;
end;
end;
f[x,y]:
=best;
end;
begin
readln(r,c);
fori:
=1tordo
forj:
=1tocdoread(a[i,j]);
fillchar(f,sizeof(f),0);
max:
=0;
fori:
=1tordo
forj:
=1tocdobegin
ifbest(i,j)>maxthenmax:
=best(i,j);
end;
writeln(max);
end.
**4·Sramoc问题(SramocProblem)
源程序名sramoc.?
?
?
(pas,c,cpp)
可执行文件名sramoc.exe
输入文件名sramoc.in
输出文件名sramoc.out
问题描述:
Sramoc(K,M)表示用数字0、1、2…、K-1组成的自然数中能被M整除的最小数。
给定K、M,求Sramoc(K,M)。
例如K=2,M=7的时候,Sramoc(2,7)=1001。
输入格式:
从文件SRAMOC.DAT读入数据。
第一行为两个整数K、M满足2<=K<=10、1<=M<=1000。
输出格式:
输出Sramoc(K,M)到SRAMOC.OUT。
样例
SRAMOC.DAT
SRAMOC.OUT
27
1001
思路:
广搜,从1位数的余数出发,不停扩展,生成新余数,直到余数0第一次出现
提交情况:
一次90分 原因直接扩展有一组的答案超出了qword的最大值……
改进思路,每次只记录一位。
90分程序如下:
programsramoc;
var
k,m:
longint;
d:
array[0..100000]ofqword;
hash:
array[0..2000]oflongint;
procedureinit;
begin
assign(input,'sramoc.in');
assign(output,'sramoc.out');
reset(input);
rewrite(output);
end;
procedureprepare;
var
i,j:
longint;
begin
readln(k,m);
end;
procedureoutit;
begin
close(input);
close(output);
halt;
end;
proceduremain;
var
l,r,i,j:
longint;
x,y:
qword;
begin
l:
=0;r:
=0;
fillchar(hash,sizeof(hash),0);
fori:
=1tok-1do
begin
d[i]:
=i;
ifd[i]modm=0thenbeginwriteln(d[i]);outit;end;
r:
=r+1;
hash[d[i]modm]:
=1;
end;
repeat
l:
=l+1;
x:
=d[l];
fori:
=0tok-1do
begin
y:
=x*10+i;
ifymodm=0thenbeginwriteln(y);outit;end;
ifhash[ymodm]=0thenbegin
r:
=r+1;
d[r]:
=y;
hash[ymodm]:
=1;
end;
end;
untill=r;
end;
begin
init;
prepare;
main;
outit;
end.
**5·黑白棋游戏
源程序名game.?
?
?
(pas,c,cpp)
可执行文件名game.exe
输入文件名game.in
输出文件名game.out
【问题描述】
黑白棋游戏的棋盘由4×4方格阵列构成。
棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。
这16枚棋子的每一种放置方案都构成一个游戏状态。
在棋盘上拥有1条公共边的2个方格称为相邻方格。
一个方格最多可有4个相邻方格。
在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。
对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。
【输入】
输入文件共有8行。
前四行是初始游戏状态,后四行是目标游戏状态。
每行4个数分别表示该行放置的棋子颜色。
“0”表示白棋;“1”表示黑棋。
【输出】
输出文件的第一行是着棋步数n。
接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。
例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。
【样例】
game.ingame.out
11114
00001222
11101424
00103242
10104344
0101
1010
0101
广搜,用位运算记录及更改状态,分别处理上下交换和左右交换.
提交情况:
4次——60分前3次提交分别是输出格式不对,第4,8,12位没有单独处理
60分的程序如下(4组方案不对):
programgame;
type
mm=record
num,st,c1,c2,cn:
longint;
end;
const
p:
array[1..16,1..2]oflongint=((4,4),(4,3),(4,2),(4,1),(3,4),(3,3),(3,2),(3,1),(2,4),(2,3),(2,2),(2,1),(1,4),(1,3),(1,2),(1,1));
var
ss,tt:
array[0..4,0..4]oflongint;
d:
array[0..1000000]ofmm;
s,t:
longint;
procedureinit;
begin
assign(input,'game.in');
assign(output,'game.out');
reset(input);
rewrite(output);
end;
procedureprepare;
var
i,j,k,w:
longint;
s1,c:
string;
begin
s:
=0;t:
=0;
fori:
=1to4do
begin
readln(s1);
forj:
=1to4do
begin
c:
=s1[j];
val(c,ss[i,j]);
k:
=17-((i-1)*4+j);
s:
=s+(ss[i,j]shl(k-1));
end;
end;
fori:
=1to4do
begin
readln(s1);
forj:
=1to4do
begin
c:
=s1[j];
val(c,tt[i,j]);
k:
=17-((i-1)*4+j);
t:
=t+(tt[i,j]shl(k-1));
end;
end;
end;
procedureoutit;
begin
close(input);
close(output);
halt;
end;
procedureprint(x:
longint);
var
i,last,j,k:
longint;
begin
ifx=1thenexit;
last:
=d[x].st;
j:
=d[x].c2;
k:
=d[x].c1;
write(p[j,1],p[j,2]);
writeln(p[k,1],p[k,2]);
print(last);
end;
proceduremain;
var
i,j,l,r,x,y:
longint;
hash:
array[0..100000]ofboolean;
begin
fillchar(hash,sizeof(hash),false);
hash[s]:
=true;
d[1].num:
=s;
d[1].cn:
=0;
l:
=0;r:
=1;
repeat
l:
=l+1;
x:
=d[l].num;
fori:
=1to15do
begin
if(((xshr(i-1))and1)<>((xshr(i))and1))and(i<>4)and(i<>8)and(i<>12)
thenbegin
y:
=xxor(1shl(i-1));
y:
=yxor(1shl(i));
ifhash[y]=falsethen
begin
r:
=r+1;
d[r].num:
=y;
d[r].st:
=l;
d[r].c1:
=i;
d[r].c2:
=i+1;
d[r].cn:
=d[l].cn+1;
hash[y]:
=true;
end;
ify=tthenbeginwriteln(d[r].cn);print(r);outit;end;
end;
if(i<=12)and(((xshr(i-1))and1)<>((xshr(i+4-1))and1))
thenbegin
y:
=xxor(1shl(i-1));
y:
=yxor(1shl(i+3));
ifhash[y]=falsethen
begin
r:
=r+1;
d[r].num:
=y;
d[r].st:
=l;
d[r].c1:
=i;
d[r].c2:
=i+4;
d[r].cn:
=d[l].cn+1;
hash[y]:
=true;
end;
ify=tthenbeginwriteln(d[r].cn);print(r);outit;end;
end;
end;
untill>=r;
end;
begin
init;
prepare;
main;
outit;
end.
6·迷宫(maze.pas/c/cpp)
【问题描述】
电脑游戏中有许多令人头疼的迷宫,会花费玩家相当多的时间,你通过秘笈获得了游戏迷宫的地图,你希望找到最短的一条走出迷宫的道路,并且想知道一共有多少条最短的道路,但是由于地图非常庞大,所以你不能在短时间找出这些道路,因此,你需要编写一个程序来找出这些最短的道路,并且统计一下一共有多少条这样的道路。
例如,对于下图所示的迷宫:
S
X
X
X
X
E
X表示障碍物,不可以通过,S表示迷宫的入口,E表示迷宫的出口。
显然,从入口到出口至少需要走6步,而长度为6的道路一共有两条。
输入文件maze.in,第一行是一个整数n(1≤n≤25),表示迷宫是一个n×n的矩阵。
以下n行每行有n个字符来描述地图,“.”表示可以通过,“X”表示不可以通过,“S”表示迷宫的入口,“E”表示迷宫的出口。
(注意:
所有的字母均为大写)。
输出文件maze.out包括两行,第一行包含一个整数,表示从入口到出口走的最短距离。
第二行包含一个整数,表示最短路径的调数,答案保证小于231。
【样例输入】
4
…S
.XX.
.XX.
E...
【样例输出】
6
2
写两个广搜先找距离再找条数(此程序用动规的思想,写的类似广搜)
提交情况:
一次ac
programmaze;
var
map:
array[0..50,0..50]ofchar;
a,b:
array[0..850,0..50]oflongint;
n,sx,sy,ex,ey:
longint;
procedureinit;
begin
assign(input,'maze.in');
assign(output,'maze.out');
reset(input);
rewrite(output);
end;
procedureprepare;
var
i,j:
longint;
begin
readln(n);
fori:
=1tondo
begin
forj:
=1tondo
begin
read(map[i,j]);
ifmap[i,j]='S'thenbeginsx:
=i;sy:
=j;end;
ifmap[i,j]='E'thenbeginex:
=i;ey:
=j;end;
end;
readln;
end;
end;
procedureoutit;
begin
close(input);
close(output);
end;
procedurechang;
var
i,j,f,t:
longint;
dui:
array[1..2000,1..2]oflongint;
begin
fori:
=1tondo
forj:
=1tondo
a[i,j]:
=-1;
f:
=0;t:
=1;
a[sx,sy]:
=0;
dui[1,1]:
=sx;dui[1,2]:
=sy;
repeat
f:
=f+1;
i:
=dui[f,1];
j:
=dui[f,2];
if(a[i-1,j]<0)and(map[i-1,j]<>'X')
thenbegin
t:
=t+1;
a[i-1,j]:
=a[i,j]+1;
dui[t,1]:
=i-1;dui[t,2]:
=j;
end;
if(a[i+1,j]<0)and(map[i+1,j]<>'X')
thenbegin
t:
=t+1;
a[i+1,j]:
=a[i,j]+1;
dui[t,1]:
=i+1;dui[t,2]:
=j;
end;
if(a[i,j-1]<0)and(map[i,j-1]<>'X')
thenbegin
t:
=t+1;
a[i,j-1]:
=a[i,j]+1;
dui[t,1]:
=i;dui[t,2]:
=j-1;
end;
if(a[i,j+1]<0)and(map[i,j+1]<>'X')
thenbegin
t:
=t+1;
a[i,j+1]:
=a[i,j]+1;
dui[t,1]:
=i;dui[t,2]:
=j+1;
end;
ifa[ex,ey]>0thenexit;
untilf>=t;
end;
procedurelujin;
var
i,j,f,t:
longint;
dui:
array[1..2000,1..2]oflongint;
k:
array[0..50,0..50]ofboolean;
be