算法试题之二(7)

2019-08-01 23:29

当(两物体在一起而且)代码和为3或5时,必然是相克物体在一起的情况。 【参考程序】 const

wt:array[0..3]of string[5]=(' ', 'WOLF ','SHEEP','LEAVE'); var left,right:array[1..3] of integer ;

what,i,total,left_rest,right_rest:integer; procedure print_left; {输出左岸的物体} var i:integer; begin

total:=total+1;

write('(',total,')'); {第几次渡河} for i:=1 to 3 do write(wt[left[i]]); write('|',' ':4); end;

procedure print_right;{输出右岸的物体} var i:integer; begin

write(' ':4,'|');

for i:=1 to 3 do if right[i]<>0 then write(wt[right[i]]); writeln; end;

procedure print_back(whinteger); {右岸矛盾时,需从右岸捎物体→左岸} var i:integer; begin

for i:=1 to 3 do begin

if not ((i=who) or (right[i]=0)) then begin

{要捎回左岸的物体不会时刚刚从左岸带来的物体,也不会是不在右岸的物体} what:=right[i]; right[i]:=0;

print_left; {输出返回过程} write('<-',wt[i]); print_right;

left[i]:=what; {物体到达左岸} end; end; end; begin

total:=0;

for i:=1 to 3 do begin left[i]:=i; right[i]:=0;end; repeat

- 31 -

for i:=1 to 3 do {共有3种物体}

if left[i]<>0 then {第I种物体在左岸} begin

what:=left[i];left[i]:=0; {what:放置将要过河的物体编号} left_rest:=left[1]+left[2]+left[3]; {求左岸剩余的物体编号总和} if (left_rest=3) or (left_rest=5) then left[i]:=what

{假如左岸矛盾,则不能带第I种过河,尝试下一物体} else {否则可带过河}

begin print_left; {输出过河过程} write('->',wt[i]); print_right;

right[i]:=what; {物体到达右岸}

if left_rest=0 then halt; {左岸物体已悉数过河} right_rest:=right[1]+right[2]+right[3];

{求右岸剩余的物体编号总和} if (right_rest=3)or(right_rest=5) then print_back(i) {右岸有矛盾,要捎物体回左岸}

else begin print_left; {右岸有矛盾,空手回左岸} write('<-',' ':5); print_right; end; end; end;

until false; {不断往返} end.

2.【题目】 把1-8这8个数放入下图8个格中,要求相邻的格(横,竖,对角线)上填的数不连续. ┌─┐ │①│ ┌─┼─┼─┐ │②│③│④│ ├─┼─┼─┤ │⑤│⑥│⑦│ └─┼─┼─┘ │⑧│ └─┘

【参考程序】

const lin:array[1..8] of set of 1..8 =

([3,2,4],[1,6,3,5],[5,7,1,2,4,6],[1,6,3,7], [3,8,2,6],[2,4,3,5,7,8],[3,8,4,6],[5,7,6]); var a:array[1..8] of integer;

total,i:integer; had:set of 1..8;

function ok(dep,i:integer):boolean; {判断是否能在第dep格放数字i} var j:integer; begin

ok:=true;

for j:=1 to 8 do {相邻且连续则不行}

if (j in lin[dep]) and (abs(i-a[j])=1) then ok:=false; if i in had then ok:=false; {已用过的也不行} end;

- 32 -

procedure output; {输出一种方案} var j:integer; begin

inc(total); write(total,':');

for j:=1 to 8 do write(a[j]:2);writeln; end;

procedure find(dep:byte); var i:byte; begin

for i:=1 to 8 do begin {每一格可能放1-8这8个数字中的一个} if ok(dep,i) then begin

a[dep]:=i; {把i放入格中}

had:=had+[i]; {设置已放过标志} if (dep=8) then output else find(dep+1);

a[dep]:=10; {回溯,恢复原状态} had:=had-[i]; end; end; end; begin

fillchar(a,sizeof(a),10); total:=0; had:=[]; find(1);

writeln('End.'); end.

3.【题目】迷宫问题.求迷宫的路径.(深度优先搜索法) 【参考程序1】 const

Road:array[1..8,1..8]of 0..3=((1,0,0,0,0,0,0,0), (0,1,1,1,1,0,1,0), (0,0,0,0,1,0,1,0), (0,1,0,0,0,0,1,0), (0,1,0,1,1,0,1,0), (0,1,0,0,0,0,1,1), (0,1,0,0,1,0,0,0), (0,1,1,1,1,1,1,0)); {迷宫数组}

FangXiang:array[1..4,1..2]of -1..1=((1,0),(0,1),(-1,0),(0,-1));{四个移动方向} WayIn:array[1..2]of byte=(1,1); {入口坐标} WayOut:array[1..2]of byte=(8,8); {出口坐标} Var i,j,Total:integer;

Procedure Output; var i,j:integer; Begin

For i:=1 to 8 do begin for j:=1 to 8 do begin if Road[i,j]=1 then write(#219); {1:墙} if Road[i,j]=2 then write(' '); {2:曾走过但不通的路}

- 33 -

if Road[i,j]=3 then write(#03) ; {3:沿途走过的畅通的路} if Road[i,j]=0 then write(' ') ; {0:原本就可行的路} end; writeln;

end; inc(total); {统计总数} readln; end;

Function Ok(x,y,i:byte):boolean; {判断坐标(X,Y)在第I个方向上是否可行} Var NewX,NewY:shortint; Begin

Ok:=True;

Newx:=x+FangXiang[i,1]; Newy:=y+FangXiang[i,2];

If not((NewX in [1..8]) and (NewY in [1..8])) then Ok:=False; {超界?} If Road[NewX,NewY]=3 then ok:=false; {是否已走过的路?} If Road[NewX,NewY]=1 then ok:=false; {是否墙?} End;

Procedure Howgo(x,y:integer); Var i,NewX,NewY:integer; Begin

For i:=1 to 4 do Begin {每一步均有4个方向可选择} If Ok(x,y,i) then Begin {判断某一方向是否可前进} Newx:=x+FangXiang[i,1]; {前进,产生新的坐标} Newy:=y+FangXiang[i,2]; Road[Newx,Newy]:=3; {来到新位置后,设置已走过标志} If (NewX=WayOut[1]) and(NewY=WayOut[2]) Then Output Else Howgo(Newx,NewY); {如到出口则输出,否则下一步递归} Road[Newx,Newy]:=2; {堵死某一方向,不让再走,以免打转} end; end; End;

Begin

total:=0;

Road[wayin[1],wayin[2]]:=3; {入口坐标设置已走标志} Howgo(wayin[1],wayin[2]); {从入口处开始搜索} writeln('Total is ',total); {统计总数} end.

4.【题目】地图着色问题 【参考程序1】

const lin:array[1..12,1..12] of 0..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),

- 34 -

(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));

var color:array[1..12] of byte; {color数组放已填的颜色} total:integer;

function ok(dep,i:byte):boolean; {判断选用色i是否可用} var k:byte; {条件:相邻的区域颜色不能相同} begin

for k:=1 to dep do

if (lin[dep,k]=1) and (i=color[k]) then begin ok:=false;exit;end; ok:=true; end;

procedure output; {输出} var k:byte; begin

for k:=1 to 12 do write(color[k],' ');writeln; total:=total+1; end;

procedure find(dep:byte); {参数dep:当前正在填的层数} var i:byte; begin

for i:=1 to 4 do begin {每个区域都可能是1-4种颜色} if ok(dep,i) then begin color[dep]:=i;

if dep=12 then output else find(dep+1);

color[dep]:=0; {恢复初始状态,以便下一次搜索} end; end; end;

begin

total:=0; {总数初始化}

fillchar(color,sizeof(color),0); find(1);

writeln('total:=',total); end.

5.【题目】一笔画问题

从某一点出发,经过每条边一次且仅一次.(具体图见高级本P160) 【参考程序】

const max=6;{顶点数为6}

type shuzu=array[1..max,1..max]of 0..max; const a:shuzu {图的描述与定义 1:连通;0:不通} =((0,1,0,1,1,1), (1,0,1,0,1,0), (0,1,0,1,1,1), (1,0,1,0,1,1),

- 35 -


算法试题之二(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:论国际私法中的公共秩序保留制度

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: