“过河”问题的解法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
“过河”问题的解法
陕西省西安市长安区第二中学杨西武
【关键词】
迪克斯特拉算法,图论,最短路径
【内容提要】
信息学奥林匹克竞赛,各类资料中都涉及“过河”一题,但都没有给出详解及程序。历届考题也没有涉及到,原因是其测试数据不便给出多组。但此题对考察学生的分析能力和解题能力却很有帮助。本文旨在给出其详解。
【问题描述】
某人m带一只羊s,一只狼w和一筐白菜v过河。没有船,他每次游过河时只能带一件东西,当没有人管理时,狼和羊不能相处,羊和白菜不能相处。在这些条件的约束下,他怎样才能将三件东西从左岸带往右岸?试编程给出一组过河次数最少的方案。【问题分析】
用无向图描述上述问题的解法路径
用结点代表状态
例如:初始状态v1可记为
{}>
Φ
<,
,
,
,v
w
s
m(即,人、羊、狼、
白菜皆在左岸,右岸为空,这是一种安全状态,即满足约束条件
的状态)。最终状态v10可记为
{}>
Φ
w s m, , , ,; 当人和羊过河后的状态可记为 {}{}> m v w, , ,(即,狼和白菜 在左岸,人和羊在右岸,这也是一种完全状态)。 可根据约束条件写出所有的安全状态: 即:①{}> Φ <, , , ,v w s m ②{}{}> m v w, , , ③ {}{}> v w m, , , ④ {}{}> v s m, , , ⑤ {}{}> w s m, , , ⑥ {}{}> w s m, , , ⑦ {}{}> w m s, , , ⑧ {}{}> s m w, , , ⑨{}{}> ⑩{}>Φ 将这些安全状态分别用结点v1v2……v10表示 若结点vi 经过一次过河可以到达结点vj ,则可以认为vi 和vj 之间有一条边,于是可以得到如下无向图: 从v1到v10的一条路径,即表示该题的一种解法 求过河次数最少的的方案也就是该图的一条最短路径 【算法】 ①模拟题意,找出所有安全状态(见过程starter ) ②模拟题意,找出各结点之间的关联,即建立图(见过程create ) ③用迪克斯特拉算法,求出最短路径并打印。 【源代码】 program MWSV; type way=record num:integer; dist:integer; next:0..16; end; boat=record m,w,s,v:0..1; end; var b:array[1..16]of boat; n:integer; V 4 9 r:array[1..16,1..16]of 0..1; procedure starter; {根据约束条件,求出所有安全状态} var bb:boat;mm,ww,ss,vv:0..1; begin n:=0; for mm:=0 to 1 do for ww:=0 to 1 do for ss:=0 to 1 do for vv:=0 to 1 do if not((ss<>mm)and((ss=ww)or(ss=vv)))then begin inc(n); b[n].m:=mm; b[n].s:=ss; b[n].w:=ww; b[n].v:=vv; end; end; procedure create; {根据渡河条件,建立各结点间的联系} var i,j:integer; function ifln(b1,b2:boat):boolean; var a,b:0..4;bz:boat; begin if b1.m<>1 then begin bz:=b1; b1:=b2; b2:=bz; end; a:=b1.m+b1.w+b1.s+b1.v; b:=b2.m+b2.w+b2.s+b2.v; ifln:=false; if (b1.m+b2.m=1)and(a<>b)and(abs(a-b)<3)then if not((b1.w=0)and(b2.w=1)or(b1.s=0)and(b2.s=1)or(b1.v=0)and(b2.v=1) ) then ifln:=true; end; begin for i:=1 to n do for j:=1 to n do r[i,j]:=0; for i:=1 to n do for j:=i+1 to n do if ifln(b[i],b[j]) then begin