数学建模社区-数学中国

标题: 渡河问题 [打印本页]

作者: sally    时间: 2004-6-5 11:57
标题: 渡河问题

渡河问题

- U; s8 u n$ e9 b$ X: T4 z6 a

A wolf, a goat and a cabbage are on one bank of a river. A ferryman wants to take them across, but since his boat is small, he can take only one of them at a time. For obvious reasons, neither the wolf and the goat nor the goat and the cabbage can be left unguarded. How is the ferryman going to get them across the river?

: i5 O. A) r: |' e' v6 [8 o* c$ m! B

1 e8 K% Y' y$ Y+ V; D6 \6 `7 H

程序代码:

2 c+ y% e' P( Q& x9 G. }8 {, {

//以下程序在Win98+vc6.0运行通过

3 L+ X+ ]+ i. U8 q* L$ k

#include <stdio.h>. U( C* {" o g" k: o4 q( F #include <stdlib.h> , e+ U* ?: q4 s$ {- M#define MAX 50 : a8 a$ Z- C3 V" ?: H6 I7 d$ sstruct state ' u- y; }& O) d. n{& G, B3 w! A6 F int man,sheep,wolf,cabbage;//0:在起始岸;1:在目的岸1 U0 P+ I& Q8 f8 t! e int m;//所采取的过河方法,(1--4)% @7 G7 p2 b j+ W }s[MAX];0 p# |7 h1 J. t) P9 N int count=0; 8 s4 R, s# Q( E( }FILE *fp=fopen("c:\\2.txt","w+");

5 \ U& R+ ~9 D2 r" \2 V% D

void main() 3 Z& z9 j5 t7 T* n, q# N{ - L' Z* ?8 R5 ]! T void f1(int ),f2();//f1试探递归4 E* [% R+ E' U1 I# |; D s[0].man=s[0].sheep=s[0].wolf=s[0].cabbage=0;) d$ F$ S9 V/ Y0 U S s[0].m=4; 2 E2 Y+ o; k4 u3 t- x s[1].man=s[1].sheep=s[1].wolf=s[1].cabbage=0; 3 M! c' G2 K1 R; T! ? f1(1); / ?$ Y7 m( b5 d# g //f2();+ r9 }! i7 X8 I# \ fclose(fp);, C2 [# }8 [6 k" F" j2 a& o6 f printf("\n");

/ B5 c. b6 c3 ]+ o3 {

} 5 F' [. M. J0 w//用m值决定的方法渡河,成功返回1,否则返回0 7 r7 O8 V) \+ {* G, L& dint move(int top,int m)+ i& z, Z0 d4 a0 h5 [2 T2 K, } { - w& x0 {) w/ M4 E switch(m). k' h) h6 f7 p9 M {$ H6 ^4 G9 Q, x9 y! _8 C7 Z //人带羊过河3 U/ _8 H# b% d+ [ case 1: ' E8 ?' T; A# a! X# T! r3 M //判断人羊是否在同岸 3 B! Z% Z% K! j$ z if(s[top].man!=s[top].sheep) ( F; h4 \# |) q return 0;, i- T P3 O; E s[top].sheep=s[top].man=(s[top].man==1)?0:1;$ C- H4 L, H' L7 ]" Z5 S s[top].m=m;//存储过河方法0 S$ ^" b6 X$ ^+ _- g& l$ q break;' ?( { @* a: S case 2: ; _4 A: G4 c/ l if(s[top].man!=s[top].wolf) - Z" ^ |( I5 _. M0 G( \ return 0; 1 f ]/ Q6 b' m' r5 d! a s[top].wolf=s[top].man=(s[top].man==1)?0:1; 2 h2 h8 L0 c" f! l0 x8 P x s[top].m=m;//存储过河方法 - V& I2 ]% U2 C break; 1 ^& z: m9 i! { case 3: . Z+ T6 X1 I$ R: O3 Y, u6 ^9 C if(s[top].man!=s[top].cabbage) 8 z. P1 J8 r. L6 T% ^. r7 ^, Y return 0; , s, B6 J4 ]9 `1 E$ U s[top].cabbage=s[top].man=(s[top].man==1)?0:1;* J' i5 B& Z3 D) i# _9 j$ g7 _ s[top].m=m;//存储过河方法 + L; n' I6 R0 p4 P break;) i8 E. i# \1 M: { //人单独过河 + f5 c7 I1 G+ |; b3 [7 M case 4: 4 n) b0 Y; K, L8 M. [ s[top].man=(s[top].man==1)?0:1; 1 D* I5 f% K' _4 ? s[top].m=m;//存储过河方法: K) f& k3 C( x* O6 t. _. N, `, @ break;' ^+ T. `( L# A* S }//switch7 W! F" w8 m0 M! Y4 H9 O+ P/ t return 1; 6 M/ r' }& }# t2 P$ w& y I% q5 k}//move # P# S" v- c1 D( M, X//打印过河步骤 4 H' N: Y! g i# r& I/ t S5 Vvoid display(int top); B6 N/ R* D9 ]- X6 ]% O {' j: y% U7 Y3 O0 y6 O8 z6 m( j int i=0;% b, A. Q; g3 D ^" y fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);5 s$ v4 g/ h3 t+ ~ w) Q for(i=1;i<=top;i++) 2 i: _! ]; s+ e, i2 X {0 A, x7 ~3 ?5 z& ] switch(s.m) . p# [, @) c2 o/ x, A { ; u) n1 ~; L$ t" z' E8 y case 1:. h$ [$ {2 B1 N2 @, }! M; D9 Q+ _; Y if(s.man==1&&s[i-1].man==0) ! A y9 H% S& o( q; E Z; M$ {/ M fprintf(fp,"人带羊从起始岸过河到目的岸\n");' n$ j+ d& K( h% q( }* L* U else4 l9 g. L% f, v4 s- }% H fprintf(fp,"人带羊从目的岸过河到起始岸\n");& v M0 F- z9 N* u break;) F/ D- d+ }9 @; G7 U. B& H case 2:6 s1 T/ ~1 o$ a! J) K; `" O) n' F' [ if(s.man==1&&s[i-1].man==0) 1 c+ \7 A9 e9 Q7 T+ _( k. v fprintf(fp,"人带狼从起始岸过河到目的岸\n");5 `" d2 W7 \# B. K else ; U' ]9 x( G, F# Y- t" p fprintf(fp,"人带狼从目的岸过河到起始岸\n");: n3 Z. _0 _* X+ e break; & ]/ z" f- k; j7 ]( `( l0 x case 3:6 m2 x- a$ L# ~/ w if(s.man==1&&s[i-1].man==0)7 M: m: u$ S- v fprintf(fp,"人带菜从起始岸过河到目的岸\n"); % b7 O: O6 b2 k5 E6 n else0 X3 [* q* D, @; W$ e+ } fprintf(fp,"人带菜从目的岸过河到起始岸\n"); 1 {% L0 D, Y, Q$ d. Q break; % m8 r3 a) z% Y0 x9 b" J case 4:3 f: O+ E. Q2 G5 a& d4 | if(s.man==1&&s[i-1].man==0)* p F# o G6 Q9 r) \3 i$ R' ]. v fprintf(fp,"人单独从起始岸过河到目的岸\n"); 6 \( o" z( X5 l5 B' Q0 H3 G else ! @" @9 C$ w$ e7 r( j; x fprintf(fp,"人单独从目的岸过河到起始岸\n");5 G' V+ V, y$ O0 T+ V break; $ \) g9 ~ k E }//switch * [! Z; X9 M, v+ l) p! o fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);6 E7 w! n+ i- z. ]0 J t9 g$ S% J8 D7 u }//for. z8 M2 P; r$ j" ^7 X fprintf(fp,"All ferried successfully!\n");$ w8 D7 a2 D8 R, N# H; i7 { }//display

; l* j. O! o9 S. y8 Y

//检查两岸合法性已经有无状态与历史重复性 : Q7 z: c2 g" R; N8 wint check(int top) % A! w7 x* \- @2 ]' v* Z{4 \- `& q/ j( O& ]7 H8 f' {4 I int i; # N, H* s% K# }//检查两岸合法性 ' T3 p4 T6 k% f if((s[top].sheep!=s[top].man&&s[top].cabbage!=s[top].man)||% y" I5 ^) H" A7 n1 L9 w- H (s[top].wolf!=s[top].man&&s[top].sheep!=s[top].man)) 8 Y P5 f& h# J G return 0;: |7 W% c' ?/ _2 g5 r" E //检查历史重复性1 c l8 {. s1 \, J for(i=0;i<top;i++). E& j5 ^9 ~) _ _) r if(s.man==s[top].man&&s.sheep==s[top].sheep&&s.cabbage==s[top].cabbage&&s.wolf==s[top].wolf) 2 {' B4 n, K4 q6 P return 0; ' l9 D' n; l& A- s //ok1 ]2 A( }2 ?4 _7 N3 k' D C6 w return 1;" A) l& ^. c1 Y3 Y [ T }, A# L* C% ], v( E% ~" Q void f1(int top)1 M; g8 o1 ?- e' F/ ^+ e2 i { 7 g; b% }8 x1 a$ ]8 Y9 c6 \ int m; 7 y* t/ K/ Z- P# J if(top>0)//0状态(初试状态应该是预先设置好的,所以要做状态1,故,初试top进来应该是1 - |1 `, f$ S8 |8 V0 m { //对每次状态分别试探4中方案 # c D" g1 U0 N for(m=1;m<5;m++) 0 z7 X0 x3 F' d- {/ M {" W* m5 q4 z0 X( z/ r //每次方案的实施是在上次结果状态上做的 5 w% Q# f+ @+ K5 O! |3 ]$ x' W s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;6 r5 }" t' z8 p0 x s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf; : T6 D1 d3 S2 u* P; H //用方案m移动,同时检查结果 4 r+ w2 g& K4 @ if(move(top,m)&&check(top))+ A! u6 Y2 `2 u { ( y6 h. i& n3 j9 {0 Z if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf ) : x$ ~! D p+ A* I/ d2 L+ [, O {1 x2 {4 A( n' u: y6 A9 _+ i6 x o. ^; j //打印渡河步骤 . u$ t% j4 v% T, V/ `0 y5 _) e display(top);3 U O7 |% `$ T* C1 F9 D- O+ H8 \6 k //统计方案个数 . m/ ?4 L1 L& ^% N count++; : s) h- V' m# [* A7 F fprintf(fp,"count=%d----------------------------\n\n",count); 8 L& C. p/ h8 D" m0 @3 F if(count>1000) exit(1);6 \9 Q$ w! }# t; r# Y3 j! N' l1 ~ } . j6 m, i7 f8 L+ k else 4 T0 W1 t3 O' v f1(top+1);9 u: @$ t5 N) `5 C }% V/ h: J6 C# n! H }//for - c# w9 S- w' F: i/ g$ d+ r1 L) A: g }//if(top>=0) o U9 i; {% h3 a! y2 V$ c, d' ?! W}//f1

0 s& |0 C2 }5 _ ?

! L1 s1 Q7 u: `

" A; n$ G. i* s, V, h

O8 w) L5 D7 V. ^! k- Q1 z void f2(). Q) Y9 g' W2 P: g. Z9 I/ T. K* i {& _1 d. Q( b0 ?2 N int top=0,i;" a& Z$ F/ |$ l //开始时都在起始岸 5 S# P1 B2 A, g7 w3 A+ {% J s[top].man=s[top].sheep=s[top].wolf=s[top].cabbage=0; 9 z' W6 k+ w6 C, k& |% G) i //未开始渡河 / t0 [( u2 b9 d4 _8 C6 F s[top].m=4; ]7 X0 F5 g! U while(top>=0) % g5 p# A8 ^" W {6 }! _) W# q, Y4 h! `2 M& S! H if(check(top))7 N& ?8 a" `" t; H$ c { , h- k& @) O( P) V8 b if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )+ Z& E7 }: p) A6 w2 ? {1 j) W0 W5 p+ q5 b* [ //打印渡河步骤 6 _, s9 F6 }% H. {% t3 J display(top);7 M% v5 f7 d% @, U% T //统计方案个数 i! z$ k- b: Q3 @9 v# X$ a count++; , a9 @/ u! i, ~& D! Z L fprintf(fp,"count=%d----------------------------\n\n",count);. U) E" H8 X* Q* N if(count>1000) exit(1);4 k8 D, E1 ]* e u6 M; k //回溯 + j* _: ~1 e3 R1 X# R2 ?. R @ while(top>=0&&s[top].m>=4) / ]3 b7 D0 }* d# a8 F% A top--; ) Y- I; t1 @( n! C2 v$ ` if(top>=0) 3 v/ S3 a' b0 q7 D- \/ S6 B, M; q {, X; ^5 O1 c' ~9 @3 x //在上次状态基础上准备做move$ E- }" l; C' D" p3 y1 W s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep; 6 W' d& A$ l& M+ K s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf; L" h3 S5 h& K2 N: Z i=1;1 T- ?& E, Y* G! T' O& j while(s[top].m+i<5&&!move(top,s[top].m+i)) " Q+ s" {4 d+ f i++; 7 m, F; B% W& a$ g6 u9 } }

3 W+ P1 F: f# C3 G

}. U; p& k. R; q% a7 b' j: k9 c/ ~ else 6 }* T% z" `, k% p6 Z: z9 ] { / t6 v% ?( `) m top++;: J/ z. E- H' p( { //在上次状态基础上准备做move7 H9 e1 f7 i( Y- e% l. V6 _* L1 V s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;7 v0 A4 \$ N' B/ p5 @# J s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;; U2 X8 L3 H* ^, I5 N i=1;) A) Y0 L% f7 |4 l. }5 | while(i<5&&!move(top,i)) 1 O9 d5 r9 [) A2 m i++;$ _/ \! j7 W8 u5 r% V }

0 @& s/ j3 R6 F- J! r

} . S2 k) t" N' g8 w& y! E1 y else # ~2 Z a! X9 | {: M5 J. K8 S) z9 c v0 T8 N0 U4 ~5 ] //回溯 ' t4 a3 z5 Y6 O8 H0 v7 p while(top>=0&&s[top].m>=4) ) f2 B% z. {# p2 V top--; 4 B4 r m! \' H if(top>=0)! v; j7 K9 }4 d3 x1 [! }+ q {$ n0 c* j+ ]7 s9 s //在上次状态基础上准备做move & n0 ]) }6 a1 |% }% @* L s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;0 k! {- g. A, i4 D- W s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;/ y: L' L7 l# P' G" n$ i i=1; 6 P, P5 y7 E( P7 T while(!move(top,s[top].m+i)) 6 ^) A" ]- M( y9 B i++;' G5 w. }( T9 \- I& Q% e. j } }, ^; G% L/ K }$ }$ L A' D& ?# d0 {; t7 f; z }//while) R: |2 v" r3 [9 t! Z) f' I$ r }//f2) a& L7 m) C; { C# l //---------------------------------2 c, G* @) K* z7 g


作者: sally    时间: 2004-6-5 12:07
也可以转化为图的遍历问题
作者: huashi3483    时间: 2004-6-6 18:58
呵呵,好搭档
作者: lynn324    时间: 2004-12-4 16:19
是用c编的吗?
作者: mnpfc    时间: 2009-8-15 06:56
呵呵,看过了




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5