算法试题之二(8)

2019-08-01 23:29

(1,1,1,1,0,0), (1,0,1,1,0,0)); var

bianshu:array[1..max]of 0..max; {与每一条边相连的边数} path:array[0..1000]of integer; {记录画法,只记录顶点} zongbianshu,ii,first,i,total:integer;

procedure output(dep:integer); {输出各个顶点的画法顺序} var sum,i,j:integer; begin

inc(total);

writeln('total:',total);

for i:=0 to dep do write(Path[i]);writeln; end;

function ok(now,i:integer;var next:integer):boolean;{判断第I条连接边是否已行过} var j,jj:integer; begin

j:=0; jj:=0;

while jj<>i do begin inc(j);if a[now,j]<>0 then inc(jj);end; next:=j;

{判断当前顶点的第I条连接边的另一端是哪个顶点,找出后赋给NEXT传回} ok:=true;

if (a[now,j]<>1) then ok:=false; {A[I,J]=0:原本不通} end; { =2:曾走过}

procedure init; {初始化} var i,j :integer; begin

total:=0; {方案总数} zongbianshu:=0; {总边数} for i:=1 to max do for j:=1 to max do if a[i,j]<>0 then begin inc(bianshu[i]);inc(zongbianshu);end; {求与每一边连接的边数bianshu[i]}

zongbianshu:=zongbianshu div 2; {图中的总边数} end;

procedure find(dep,nowpoint:integer); {dep:画第几条边;nowpoint:现在所处的顶点} var i,next,j:integer; begin

for i:=1 to bianshu[nowpoint] do {与当前顶点有多少条相接,则有多少种走法} if ok(nowpoint,i,next) then begin {与当前顶点相接的第I条边可行吗?} {如果可行,其求出另一端点是NEXT} a[nowpoint,next]:=2; a[next,nowpoint]:=2; {置成已走过标志} path[dep]:=next; {记录顶点,方便输出} if dep < zongbianshu then find(dep+1,next) {未搜索完每一条边} else output(dep); path[dep]:=0; {回溯}

- 36 -

a[nowpoint,next]:=1; a[next,nowpoint]:=1; end;

begin

init; {初始化,求边数等}

for first:=1 to max do {分别从各个顶点出发,尝试一笔画} fillchar(path,sizeof(path),0); path[0]:=first; {记录其起始的顶点} writeln('from point ',first,':');readln;

find(1,first); {从起始点first,一条边一条边地画下去} end.

6.【题目】城市遍历问题.

给出六个城市的道路连接图,找出从某一城市出发,遍历每个城市一次且仅一次的最短路径 及其路程长度.(图见高级本P147} 【参考程序】 const

a:array[1..6,1..6]of 0..10 {城市间连接图.数字表示两城市间的路程} =((0,4,8,0,0,0), (4,0,3,4,6,0), (8,3,0,2,2,0), (0,4,2,0,4,9), (0,6,2,4,0,4), (0,0,0,9,4,0)); var

had:array[1..6]of boolean; {某个城市是否已到过} pathmin,path:array[1..6]of integer; {记录遍历顺序} ii,first,i,summin,total:integer;

procedure output(dep:integer); sum,i,j:integer; sum:=0; i:=2 6 {求这条路的路程总长} if sum><6 then find(dep+1)

else output(dep); had[i]:=false; {回溯} path[dep]:=0; end; end;

begin

for first:=1 to 6 do begin {轮流从每一个城市出发,寻找各自的最短路} fillchar(had,sizeof(had),false); fillchar(path,sizeof(path),0); total:=0;

SumMin:=maxint; {最短路程}

path[1]:=first;had[first]:=true;{处理出发点的城市信息,记录在册并置到过标志} find(2); {到下一城市}

writeln('from city ',first,' start,total is:',total,' the min sum:',summin);

for i:=1 to 6 do write(PathMin[i]);writeln; {输出某个城市出发的最短方案} end; end.

- 37 -

7.【题目】马的遍历问题。在N*M的棋盘中,马只能走日字。马从位置(x,y)处出发,把 棋盘的每一格都走一次,且只走一次。找出所有路径。 【参考程序】 {深度优先搜索法} const n=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]of byte; {记录走法数组} procedure output; {输出,并统计总数} var x,y:byte; begin

cont:=cont+1; writeln; writeln('count=',cont); for y:=1 to n do begin

for x:=1 to m do write(a[y,x]:3); writeln; end; { readln; halt;} end;

procedure find(y,x,dep:byte); var i,xx,yy:integer; begin

for i:=1 to 8 do begin

xx:=x+fx[i,1];yy:=y+fx[i,2]; {加上方向增量,形成新的坐标} if ((xx in [1..m])and(yy in [1..n]))and(a[yy,xx]=0) then {判断新坐标是否出界,是否已走过?} begin

a[yy,xx]:=dep; {走向新的坐标} if (dep=n*m) then output

else find(yy,xx,dep+1); {从新坐标出发,递归下一层} a[yy,xx]:=0 {回溯,恢复未走标志} end; end; end;

begin cont:=0;

fillchar(a,sizeof(a),0); dep:=1;

writeln('input y,x');readln(y,x); { x:=1;y:=1;}

if (y>n) or(x>m) then begin writeln('x,y error!');halt;end; a[y,x]:=1; find(y,x,2);

if cont=0 then writeln('No answer!') else write('The End!'); readln; end.

- 38 -

8.【题目】把自然数N分解为若干个自然数之积。 【参考程序】

var path :array[1..1000] of integer; total,n:integer;

procedure find(k,sum,dep:integer); {K:} var b,d:Integer; begin

if sum=n then {积等于N} begin

write(n,'=',path[1]);

for d:=2 to dep-1 do write('*',path[d]); writeln;inc(total); exit; end;

if sum>n then exit; {累积大于N}

for b:= trunc(n/sum)+1 downto k do {每一种可能都去试} 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.

9.【题目】把自然数N分解为若干个自然数之和。 【参考答案】 n │ total 5 │ 7 6 │ 11 7 │ 15 10 │ 42

100 │ 190569291

【参考程序】

var n:byte; num:array[0..255] of byte; total:word; procedure output(dep:byte); var j:byte; begin

for j:=1 to dep do write(num[j]:3);writeln; inc(total); end;

procedure find(n,dep:byte); {N:待分解的数,DEP:深度} var i,j,rest:byte; begin

for i:=1 to n do {每一位从N到1去试}

- 39 -

if num[dep-1]<=i then {保证选用的数大于前一位} begin num[dep]:=i;

rest:=n - i; {剩余的数进行下一次递归调用} if (rest>0) then begin find(rest,dep+1);end

else if rest=0 then output(dep);{刚好相等则输出} num[dep]:=0; end; end;

begin {主程序}

writeln('input n:');readln(n); fillchar(num,sizeof(num),0); total:=0; num[0]:=0; find(n,1);

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

10.【题目】N皇后问题(含八皇后问题的扩展,规则同八皇后):在N*N的棋盘上,放置N个皇后,要求每一横行

每一列,每一对角线上均只能放置一个皇后,问可能的方案及方案数。 const max=8; var i,j:integer;

a:array[1..max] of 0..max; {放皇后数组}

b:array[2..2*max] of boolean; {/对角线标志数组}

c:array[-(max-1)..max-1] of boolean; {\\对角线标志数组} col:array[1..max] of boolean; {列标志数组} total:integer; {统计总数} procedure output; {输出} var i:integer; begin

write('No.':4,'[',total+1:2,']');

for i:=1 to max do write(a[i]:3);write(' '); if (total+1) mod 2 =0 then writeln; inc(total); end;

function ok(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) then ok:=true end;

procedure try(dep:integer); var i,j:integer; begin

for i:=1 to max do {每一行均有max种放法} if ok(i,dep) then begin a[dep]:=i;

b[i+dep]:=false; {/对角线已放标志} c[dep-i]:=false; {\\对角线已放标志}

- 40 -

col[i]:=false; {列已放标志} if dep=max then output

else try(dep+1); {递归下一层} a[dep]:=0; {取走皇后,回溯} b[i+dep]:=true; {恢复标志数组} c[dep-i]:=true; col[i]:=true; end; end; begin

for i:=1 to max do begin a[i]:=0;col[i]:=true;end; for i:=2 to 2*max do b[i]:=true;

for i:=-(max-1) to max-1 do c[i]:=true; total:=0; try(1);

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

【测试数据】 n=8 八皇后问题 total:92

对于N皇后: ┏━━━┯━━┯━━┯━━┯━━┯━━┯━━┯━━┓ ┃皇后 N│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 ┃ ┠───┼──┼──┼──┼──┼──┼──┼──┨ ┃方案数│ 2 │ 10 │ 4 │ 40 │ 92 │352 │724 ┃ ┗━━━┷━━┷━━┷━━┷━━┷━━┷━━┷━━┛

- 41 -


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

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

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

马上注册会员

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