数学建模社区-数学中国

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

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

渡河问题

& |: H8 y3 r8 ?0 i `9 Q) X1 H/ x

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?

, V- ]! v2 Y" k3 C" c+ [

3 M% H' X/ b4 f, l: j( {

程序代码:

, P" {' z% R7 C1 `6 u) J' b; |% m0 _

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

9 y' Q- d( ]7 ?) d" I& T, v9 J

#include <stdio.h>" ?6 ?/ f M$ ?4 M- P #include <stdlib.h>2 W- H7 \7 _$ n( L' x3 `" a #define MAX 50# h" S' z! C) h. m, b7 w struct state + }7 A5 N1 m% }7 e: q{8 f0 A/ t( x" \8 w( q4 U( a. ] int man,sheep,wolf,cabbage;//0:在起始岸;1:在目的岸: m2 q$ i2 E' }! L, C$ x int m;//所采取的过河方法,(1--4) 7 G9 a- U, j4 P}s[MAX];* x4 H4 @4 ?/ k: y$ n: j' q- K int count=0;& Q# B8 N6 Z+ [ FILE *fp=fopen("c:\\2.txt","w+");

4 E( L. I: u" z; T! A8 q

void main() * g$ P$ {. q* w& c [{ ! y; @) W( e2 Y5 M& t void f1(int ),f2();//f1试探递归6 J( P' q0 Z$ A4 z0 R+ k8 B s[0].man=s[0].sheep=s[0].wolf=s[0].cabbage=0; ( x' W) s! L1 q$ N; P' w9 r s[0].m=4;. p$ I4 }) Z* b: x* P' Q) z s[1].man=s[1].sheep=s[1].wolf=s[1].cabbage=0;( b" Y, H/ v k8 X! F& {" D f1(1); - [' L% [& b$ q6 \. i; x6 F //f2(); * r1 T+ k4 R3 C7 `7 C3 h& r/ t' H: e fclose(fp);$ ?% N. Y8 J- ~3 T; g printf("\n");

1 ^, a& s. K* s! B, o( y5 M% L% R

}( `6 s. w% n }! }$ ~ //用m值决定的方法渡河,成功返回1,否则返回0 ' ` m, C2 d+ p3 k% ?int move(int top,int m) * K2 A- H* l4 W1 v{ 5 ?2 T* w+ d' F$ R switch(m)/ B+ p; n7 e' Y4 p5 ~% Z0 Z9 P, v {$ V# E! `9 Q5 u( |+ r* `! R //人带羊过河 # r6 X6 u" ?( r1 [5 D- L case 1: " h: x. g) @$ U; z //判断人羊是否在同岸 6 m \, l: ^7 O0 U* S- V if(s[top].man!=s[top].sheep) , @3 B& c) ~4 y, S4 l return 0; $ l. J! E, O- P6 r8 Z' _ s[top].sheep=s[top].man=(s[top].man==1)?0:1;- J: H+ F" F+ ^, S+ x s[top].m=m;//存储过河方法0 t' A# K5 s" S" U break;% U2 W5 H0 g( Z1 N. w' N case 2: 8 N" Z9 Z8 V7 K: P! _$ y+ x if(s[top].man!=s[top].wolf)' F5 a$ K* o0 [% O return 0;# A! R* H1 z/ R" ` s[top].wolf=s[top].man=(s[top].man==1)?0:1; & }& R* D4 ~8 y4 g, O s[top].m=m;//存储过河方法4 _+ ^5 u1 K9 K3 t0 @: H break;& K/ M2 C. P5 b8 b0 ]# ^ case 3:( ? Z$ w( Q& o& j0 i4 F8 q% [: H if(s[top].man!=s[top].cabbage) ; P( ?& d c. D, ?# d( H return 0;+ z S7 L3 z: ?% @' Z5 N s[top].cabbage=s[top].man=(s[top].man==1)?0:1;0 Q, e, c# i* r0 H P2 A s[top].m=m;//存储过河方法5 _, i5 @. t8 N, ~( R u$ y/ z( v break; , R/ b/ f. y. k% e' e //人单独过河, v% B {& J1 Y( V9 z case 4:: ]) P" _4 I+ [0 b# t+ R* O% t* `7 Q* n# O s[top].man=(s[top].man==1)?0:1; + Z; w- U! ?) W+ @+ R X5 g% ~, F s[top].m=m;//存储过河方法 , y% H* ~& O- C8 W! ` break;: z- N& `* _ y }//switch 1 u% b+ n+ ^$ d$ @ return 1; ( i. `3 e& f: k( z}//move ' l8 x+ p" ?- x3 K3 Q, Z) B# \! p; y//打印过河步骤 ! L/ v( {7 G9 S4 c& f' c& ~void display(int top) ) o# G3 ?/ K m6 z- d, s* u: K5 z. q{ 4 s0 M8 T: m! ~/ {% H int i=0; . _9 S& O* f* q7 i- S# F fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage); 6 h" q! J7 l5 F: c r1 k0 x* p for(i=1;i<=top;i++) W e y$ n2 X+ d, I- p: | { & D0 t0 l: _- t1 \! }5 a/ p9 P i. _ switch(s.m) 8 b9 T! u4 S& Y5 S$ J { * ?) e+ k; d m) j* _ case 1: ' ^7 n/ C. V! p if(s.man==1&&s[i-1].man==0) 4 o/ P; n5 E) C5 r$ C4 T5 q fprintf(fp,"人带羊从起始岸过河到目的岸\n");' W1 O' x# Z. F+ C9 e0 T1 ~. i$ [ else; X1 K& G( M+ u0 {& ` fprintf(fp,"人带羊从目的岸过河到起始岸\n");0 s- S# j) @' Q/ F break;- F- p& m1 h, M case 2: + e4 W# y" y# a6 B# } if(s.man==1&&s[i-1].man==0) + E5 c4 m; L) u: a' H9 b' v2 I fprintf(fp,"人带狼从起始岸过河到目的岸\n");9 A" ?* d* ~7 k else- [% a2 @! U& Y f4 {+ m fprintf(fp,"人带狼从目的岸过河到起始岸\n");, o4 S$ `( u/ t% l break;6 s' L5 y2 Y, }3 U, b case 3: 5 z8 {$ J, R2 U$ O+ Z, q# U/ E if(s.man==1&&s[i-1].man==0)4 h( W8 b7 }) J7 `" H5 O fprintf(fp,"人带菜从起始岸过河到目的岸\n"); 1 E7 s: O/ d8 h( `6 B else+ G' y$ q% w% z fprintf(fp,"人带菜从目的岸过河到起始岸\n"); " a7 @! b3 J" n3 U' f# T' `5 ` break; $ A3 k a1 [$ v case 4: 8 v$ W2 p/ e; \0 S6 O if(s.man==1&&s[i-1].man==0) ) E! p. p' u$ _4 R fprintf(fp,"人单独从起始岸过河到目的岸\n");9 x9 p) y/ i; k else. A$ u9 Z. m5 j fprintf(fp,"人单独从目的岸过河到起始岸\n");9 p: P" u1 c8 H. V break; ' E& I! S# [* R1 y }//switch 5 |; p8 y! v/ y6 m7 x6 Y fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage); 5 n- Z: @/ o, V3 P6 `1 K/ f " t* z3 c9 V4 {8 O0 s }//for ; r! D/ `9 o7 `: efprintf(fp,"All ferried successfully!\n"); " T" ]$ ]2 F ~}//display

9 q3 Z1 p: h% D* H6 H* _! @ Z

//检查两岸合法性已经有无状态与历史重复性" _2 e$ K0 Q. r$ |7 O% f8 m int check(int top) / o; w' a7 E/ d3 ?{ 1 C- u- k5 t1 r2 v7 T& M8 V ? int i; ; o8 b( Q: X+ O7 v//检查两岸合法性* v3 S1 X+ K! x( |( y if((s[top].sheep!=s[top].man&&s[top].cabbage!=s[top].man)|| 2 t6 M/ U4 x2 A/ X (s[top].wolf!=s[top].man&&s[top].sheep!=s[top].man)) g( j5 e6 B% I return 0;: Q3 B9 [: ]$ H: W! ~4 I //检查历史重复性1 M3 z3 T6 ?: x% v for(i=0;i<top;i++) 0 K2 M7 |5 F! \! E* m: k$ P if(s.man==s[top].man&&s.sheep==s[top].sheep&&s.cabbage==s[top].cabbage&&s.wolf==s[top].wolf) : ~6 F: C" V( k* t return 0;% ]' S- _8 v- _' u1 q //ok 4 Q& X$ k. }8 q* S return 1;+ M: H, J) t2 i: A$ ^7 _" g P }& N, F/ o- O2 X; J* I6 \ void f1(int top) 8 \7 P' m* e: T0 ?' Z+ r9 J{) T, D- G0 X9 `; A8 A/ { int m;' x8 M1 Z J3 s8 r( h if(top>0)//0状态(初试状态应该是预先设置好的,所以要做状态1,故,初试top进来应该是1 % n/ u Z3 l* w* {8 `* v) g { //对每次状态分别试探4中方案 / C/ L6 k o) }; }, R for(m=1;m<5;m++), [+ P2 z7 W3 M2 F+ p! m { + O0 F1 J' I+ N; g; } B //每次方案的实施是在上次结果状态上做的 Y. e* [% R1 V7 Q9 @: u* C s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep; 0 [% t6 X" A6 [3 s& | s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf; ! u* y2 @/ u4 ]' s* \& u- } //用方案m移动,同时检查结果 4 ~# G. M4 D! c; t2 w if(move(top,m)&&check(top)) % S- ^6 H* ~6 w( Q1 i0 e, M9 A/ M {) i0 T5 i9 R6 V i6 u. o& W if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf ) $ @# ^* k* F0 T6 @7 i8 {) v) G- \ {3 F$ G/ F" y' `2 i //打印渡河步骤 + e! C- `- W" I display(top);) T8 n2 k5 s, U //统计方案个数( O( o; I/ x5 o& Z count++; \9 t) S7 L p! A$ |: E! c* A8 T5 V R fprintf(fp,"count=%d----------------------------\n\n",count); 0 ^' C, j& u9 Q2 @/ g: l' B2 s7 ? if(count>1000) exit(1); ' `# X( y( I/ A! w. c9 i9 R }- w5 ~; \. f- h& B else $ _+ U+ d; U/ C/ U- ~! g f1(top+1); 7 C7 ?: g4 z, D/ F+ \ }# t" N! I% p0 I% P" J4 e }//for/ i- p6 \* r( X1 k }//if(top>=0) ) X5 E F3 R2 b; \( q}//f1

3 E9 ?! M; c, n4 P( y' ]# D. O9 c

- V9 N" q5 {, p) u- x5 R

3 E. Y, E7 v. ?$ x, J$ b( g8 Z

; F2 @' _' c0 h6 j# Z- nvoid f2() 9 R3 I% a2 C! L- O& F; f{ ) D- c5 k& T. \ int top=0,i;8 K) q8 c9 l8 z //开始时都在起始岸/ `% n" }( s7 F+ f& X% j$ w) A s[top].man=s[top].sheep=s[top].wolf=s[top].cabbage=0;. M2 O2 T* [2 m% K# D2 T //未开始渡河 1 L; J+ |2 m! C7 B6 g5 I s[top].m=4;' m7 e6 I6 ~2 x' G N while(top>=0)- e" V+ R; z/ v/ }2 @8 j {6 {7 z# Z$ j: w/ v ~8 {0 B2 ~ if(check(top)) . s, S* N9 S. {; a1 X7 C6 X: n9 b {. f- v7 H1 ]+ m9 W4 i+ B/ m. ] if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )5 c5 M H8 P: K+ [3 L {. k& d, A6 a7 E% V //打印渡河步骤 7 n3 i/ |) K+ W" w7 ^, t# ]9 b* o display(top); 0 ~1 U% ]$ @" ?1 \3 X //统计方案个数. o" ~5 ]4 Z0 }8 \" H count++; 3 V6 k' f0 Y \5 f4 m2 |9 t6 H6 T6 w fprintf(fp,"count=%d----------------------------\n\n",count); + b4 K& h1 A0 Y1 Q8 q if(count>1000) exit(1);9 U/ X9 G2 J. r //回溯$ ?$ {. f# o& X1 B9 y, n while(top>=0&&s[top].m>=4) . E% B9 p& ^; b6 p' J' ]+ j' l top--; $ y' M* t6 k. U5 G7 f" ?4 t2 B if(top>=0) % U1 i0 l; B0 @ {/ o7 p* s4 u$ J; D: Q! N //在上次状态基础上准备做move , ~& I" Z b c, l6 d3 v) {* u s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep; 7 K9 V. `' s8 \; X; v( z K2 \" V/ | s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf; 6 P* b$ v# A2 g; E. A0 n% V i=1; z: j% l5 v; Y while(s[top].m+i<5&&!move(top,s[top].m+i))7 c! `: c# q* Z. I% A3 w$ | i++; 9 H' E' o7 V9 {2 e! n) P6 k- ` }

7 y+ y0 h) K% T9 j1 P7 d

}7 a3 Z e) Y8 @" k else) H' e8 u9 ^# B# I9 I7 F {- w7 q2 H4 F# l top++; ; d3 `* w. \! ]+ i //在上次状态基础上准备做move 2 b8 M! a4 k/ x( Y s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;( n9 j, w# \( m0 } s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;/ \" w3 _6 \% p. O3 e9 N( @ i=1;2 m& h( U* N- c, H while(i<5&&!move(top,i)) - L4 m% C1 [6 f( ?! f9 x9 U' F" r i++; + V) T# ~8 q& m& V! C }

3 a: P. X9 z% _9 Y A' U3 v

}3 r, H G2 e& @) @) u" O else( m5 m. q7 p! v { d' J$ `0 L2 W& y, \! v //回溯: J) p9 P8 H2 D6 n+ f. J2 p5 G while(top>=0&&s[top].m>=4) ' q: K" |3 m% C! K( E. ~ top--;. a$ U) X) b" Z0 ~ if(top>=0)" e c3 r+ I% z5 R. e# M" a: p { 2 k- O: _5 k3 @6 J& l! G //在上次状态基础上准备做move2 d/ ~6 o) e# B7 s9 u. t: W s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;% I9 V3 m. g- q. p. C+ j2 T# o" F# v s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;, k! L4 G0 Q; H4 @. e2 y: Y! _+ } i=1; ! `4 |! {. u+ g8 H* g0 y/ S+ } while(!move(top,s[top].m+i)) ! x& q1 {- d1 y1 X2 d% K: }9 l i++;# m& h5 p7 p {- c& ~$ g }: d2 ?% c6 o) i } 3 n9 J5 Q; w' a2 o& k) L3 N0 ?2 M }//while / z9 D- _" c; `( i$ X$ k5 H4 N}//f24 u1 K' L, u8 A8 s //---------------------------------% r4 Z; l5 o: N: j. y; }& a


作者: 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