|
渡河问题 ( K/ s# ~. u! P9 v" D% t
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?
7 d# h$ B- ?7 F1 [3 p- I1 Q 7 @! c l% @9 Z4 Z. d, E2 W
程序代码: b- i. v- k2 x$ T5 G! z/ l
//以下程序在Win98+vc6.0运行通过
# u* L" F8 ~3 @( t$ R q, u#include <stdio.h>+ M7 Z- v3 s) g/ E F! f
#include <stdlib.h>0 J0 b z: Q5 `- h: p
#define MAX 50! v- p$ v# J% n3 e0 i e5 O+ ^
struct state2 Z, I, q* @" a& ^. {7 N6 f
{2 ~: M u' r7 G! e
int man,sheep,wolf,cabbage;//0:在起始岸;1:在目的岸
5 m3 F+ t+ M# s# S6 @ int m;//所采取的过河方法,(1--4)! u: x, D' y) g" M- f! O4 O
}s[MAX];6 v- t7 C& e q6 ?+ w
int count=0;5 K u% m3 `! j5 c. K& P2 Q
FILE *fp=fopen("c:\\2.txt","w+");
0 y% s( }* V- }4 u# C1 Yvoid main()
# Q6 z; J- t3 O8 K{
# T7 `8 L# T4 w void f1(int ),f2();//f1试探递归
+ V7 N# V$ I. w A9 r- } s[0].man=s[0].sheep=s[0].wolf=s[0].cabbage=0;
% B, L/ @. O- v Y5 u, `4 v s[0].m=4;2 @- H1 t0 }: g
s[1].man=s[1].sheep=s[1].wolf=s[1].cabbage=0;: E0 m4 X& Q! V2 q7 D
f1(1);" S1 U" a, e- c$ ^! x# \3 ^
//f2();& Z0 e# \9 f! }" A" j9 _) X
fclose(fp);
) z2 f1 c: J! b9 u& i printf("\n");
5 m* w" R {/ T2 h7 [5 \}1 g) m- S# m' ^
//用m值决定的方法渡河,成功返回1,否则返回0
/ Y) K I/ q2 [- m) Jint move(int top,int m)
% P3 m l0 i5 A4 M' k. d{
, N- i/ X; j2 t5 G- }& x switch(m)
; b" t& b% F; K! P+ O {1 G6 Z4 {2 m8 t$ Q5 }- Z
//人带羊过河
?- I: o4 u1 f5 N4 S! e case 1:
6 }6 X$ y9 P& G- J! L- \/ Y //判断人羊是否在同岸
4 Y. ^' S2 ~+ O4 Q& f if(s[top].man!=s[top].sheep)
, H1 c* X) S7 |5 ^% h: a0 D$ H return 0;
" C1 W6 c n3 w6 y) W: d s[top].sheep=s[top].man=(s[top].man==1)?0:1;2 J. H7 ~3 C0 K
s[top].m=m;//存储过河方法
: O% h2 b; v- D8 ?5 ^9 f4 x1 j, F break;
" N( o: u J, {. x# i case 2:
. u5 J" U0 r/ L/ C0 Z- i2 M# w if(s[top].man!=s[top].wolf)
y6 R* x7 K* r- O7 R- H' o5 ~ return 0;
0 y) z/ M$ |+ \; C s[top].wolf=s[top].man=(s[top].man==1)?0:1;
) s' u! o1 ]; s0 X" Z s[top].m=m;//存储过河方法" |& b; C* }. l: d5 r4 {
break;
1 }" E4 d: Y0 }- \% F5 k case 3:
4 u' T1 ]+ b( R' g. u if(s[top].man!=s[top].cabbage)/ v4 u( x% r- {+ e# }2 j
return 0;6 p' O$ R* ?9 D6 X5 I0 ~
s[top].cabbage=s[top].man=(s[top].man==1)?0:1;9 T* ]7 Y- M+ z
s[top].m=m;//存储过河方法
6 t P* O1 k+ k0 ^# Q9 N9 g; n break;
- S: j5 w. {* L# ~$ x5 f1 f //人单独过河
( ~$ ^) I$ B7 o; n1 S8 _, y case 4:5 y! F$ W: O) ^* L; p
s[top].man=(s[top].man==1)?0:1;6 g8 r; A/ |# y* z( C0 S
s[top].m=m;//存储过河方法) h4 M- }4 ]+ |: R9 C) ?9 q) U
break;
3 [9 H! E6 Q1 l& Y q: y& { }//switch
$ J/ j5 v9 y, M7 W3 V: \. X return 1;
/ V5 t H% `7 _# T7 J7 O}//move- v* H0 _0 x4 c( ~0 o! I
//打印过河步骤8 z2 p% @# l0 A# Y& F
void display(int top)
, A m. |" z/ L$ S! f. j1 @{
! I1 d6 d) ~) \, f+ j4 } int i=0;5 K" }$ T5 {: n- d5 B7 _
fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);
" a4 i' T0 }! p+ y; Y9 l for(i=1;i<=top;i++)
( m! }! e' I6 ]% ?. B) w- k {
9 O, P* V3 t& e3 P# n4 U0 O" L switch(s.m)
9 s# J# ?1 Y# v3 I z! O: u& l {9 M( Q2 e( M& U( P2 Q
case 1:2 h6 V c0 w! Y9 H9 P( g
if(s.man==1&&s[i-1].man==0)
- A/ `$ m$ ~' n3 h) T2 j: I- d% q5 b fprintf(fp,"人带羊从起始岸过河到目的岸\n");
; a% ^& F7 B- P5 u. g$ i% P else* u" W7 k8 K$ N1 u
fprintf(fp,"人带羊从目的岸过河到起始岸\n");
- P3 b2 V! H6 b k2 K2 E break;
A5 N/ Y6 D; C: f' c, o7 U; o case 2:* b0 Y4 g# d# V5 w* c0 p4 P
if(s.man==1&&s[i-1].man==0) g5 U5 q5 M$ P, d& T! D' p
fprintf(fp,"人带狼从起始岸过河到目的岸\n");0 y1 i+ }. ~3 h A- x4 N
else& R* p) u0 i: n+ A) d+ H
fprintf(fp,"人带狼从目的岸过河到起始岸\n");1 O8 u. O" Y' M9 {
break;0 r8 Q1 E8 n% Y0 Z
case 3:6 f u4 k. r( N' D* b1 `) D$ J
if(s.man==1&&s[i-1].man==0)
1 G8 s$ A( I. n/ | p5 G fprintf(fp,"人带菜从起始岸过河到目的岸\n");1 H7 t2 C8 r+ d. h' k w9 z
else R- }! `' G- B' X0 e
fprintf(fp,"人带菜从目的岸过河到起始岸\n");: R: ]! ?/ t* O0 J2 F6 f- v; Q
break;8 `# k+ \2 p" A. |
case 4:! T. z: k+ o j% G4 W- l, X, a
if(s.man==1&&s[i-1].man==0)
9 }0 h# z, E' \* c' c- p fprintf(fp,"人单独从起始岸过河到目的岸\n");% Q$ Z9 O/ x+ ^, r
else3 a( G8 o* ~0 L Y- H" G! c
fprintf(fp,"人单独从目的岸过河到起始岸\n");6 l( s( N: M) k4 L2 t; \
break;
5 A6 ~! p" h: ^/ w0 P4 h; U }//switch
3 A/ y% [/ @% `- h fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);0 D2 W2 x6 A9 U* [2 l" Q$ m/ V
* A* F1 [9 d7 C9 X2 }5 I* G6 @ }//for& d% n' y- n' F" e& }- g
fprintf(fp,"All ferried successfully!\n");2 j% |; S, i! \ K
}//display ; ]3 r5 l7 C/ p' Z; \. T' h
//检查两岸合法性已经有无状态与历史重复性
$ o" O- W: }6 \( \ |int check(int top)- n- o, b% m5 w# r$ T: w7 w1 H
{
! ?: Z8 p4 f' L: l/ T, V& N int i;
+ Z7 W, o( ]6 M. o//检查两岸合法性; p2 ]: t1 p' T( {4 y
if((s[top].sheep!=s[top].man&&s[top].cabbage!=s[top].man)||6 @3 ~/ h( y+ [+ p9 O2 C
(s[top].wolf!=s[top].man&&s[top].sheep!=s[top].man))
; c" J$ s M% E' Z( h, g# v return 0;: f0 {! t$ o% j% O {8 h" h
//检查历史重复性
4 i/ z2 P; d; o" O% N* m4 F for(i=0;i<top;i++)
7 }2 `5 B5 @4 M/ [3 F$ J& } if(s.man==s[top].man&&s.sheep==s[top].sheep&&s.cabbage==s[top].cabbage&&s.wolf==s[top].wolf)
& M& k3 g& ~4 r; z2 K2 f return 0;( n+ }4 ?- N; L( u2 n7 X: m
//ok
! H! U4 N+ H% t- O5 p1 ~7 ^7 w, e return 1;
) b" e2 T) u# N6 p}
' L4 G0 b6 I' ?3 wvoid f1(int top)' E7 R. V) b' ~! `/ [7 t% M% }
{
B( u4 }- a* G0 G6 a% Q; Q' B int m;
2 F! E7 b( K) F* v o( y if(top>0)//0状态(初试状态应该是预先设置好的,所以要做状态1,故,初试top进来应该是1' T: h1 v$ A, L. j* v0 k
{ //对每次状态分别试探4中方案9 G U/ G; f: s1 y
for(m=1;m<5;m++)
1 E0 f# E. S( n {! j! t& M) F |, U- `
//每次方案的实施是在上次结果状态上做的 w1 t$ a" R3 u5 g6 a
s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;2 L" u2 R7 f6 Y$ z2 w
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;
% L+ V( n& V; N) o* h //用方案m移动,同时检查结果2 v4 A2 N; }# M- |6 @/ Q
if(move(top,m)&&check(top))
( W2 Z4 |* ~) Y& d4 @ {& U8 W/ d+ R+ [+ i
if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
, K" p0 Q5 Y+ o, |2 W* M1 v {( M1 B+ j3 m' }7 n& q+ M
//打印渡河步骤4 d3 ^; M* `" {1 x! O1 N- Z
display(top);. B$ h4 Z, D0 f2 x
//统计方案个数- Q1 H& G/ R& x* S( l1 ]
count++; 2 J$ O% w. G) ?7 ~9 h( F( t
fprintf(fp,"count=%d----------------------------\n\n",count);' |5 u- |2 ^, B4 ]! k! }0 K
if(count>1000) exit(1);* X' q. A. W6 s
}
5 W/ {: T6 `6 m- w2 g U! u* j else
/ }2 u& C4 Y" g: z1 z% b* O f1(top+1);
8 S e+ _/ B2 \& x; o1 E5 [ K }0 v/ |6 M* h$ i! ]" x! K: d
}//for! d. M- q5 ], g! M
}//if(top>=0)& d: m% v& o' K$ Z
}//f1 $ A P1 M5 |1 f# Y9 |$ Q
! }- d( Z( a# n8 k4 l# Y$ H2 a - {4 @; a( ?+ s- `; }7 U+ f& R
7 G+ K0 F8 ^7 Avoid f2()9 @* i" Z+ z6 n+ s4 L9 Q0 f1 y
{
: I' d1 `- r4 T1 a6 h int top=0,i;
! s' Z& @3 `/ F, O! s //开始时都在起始岸
. `7 t2 e1 V6 O% R- W! f; G* d s[top].man=s[top].sheep=s[top].wolf=s[top].cabbage=0;* n. \3 T' }' d5 D4 ?
//未开始渡河
1 I$ m' p0 t/ N9 z/ F, |0 K) p4 Z- d s[top].m=4;
G# f! R+ Q' o, ` while(top>=0)( X& u% Q7 ~- O N! T# j. r7 r+ `
{, ~' B+ c& Z- V: |8 R" `
if(check(top))
; n1 i& O- |) D& v {4 [/ w. r- J. T1 }8 D
if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
3 k8 h6 {% Z) b+ F0 } {$ ?9 a# v5 o" ~, Y3 n' N
//打印渡河步骤" k) a4 ^8 X2 w% ?
display(top);
) ]$ ~2 h& e ^ //统计方案个数: s7 E" c! N* B. I
count++; x" ?0 {" J z* _) ~( y4 z
fprintf(fp,"count=%d----------------------------\n\n",count);$ c, v* K% \4 {! a' E, J% Z
if(count>1000) exit(1);& l1 i/ i$ O# v5 I3 v" E
//回溯
7 y* N$ s8 Y) p: ^* H" k while(top>=0&&s[top].m>=4) 0 c% O& x w$ q
top--;
* b, s, K: b' ]" Y" y$ c if(top>=0)1 g5 u" ?' N& p% y$ K0 X8 ~$ J
{% M: B) v2 T- p1 {) y. Y8 ]3 w
//在上次状态基础上准备做move
% L. g$ |; d& [ s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;
1 j' A4 g% L, y& @$ m( e) G s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;2 _4 Y* ?8 |" w9 v
i=1;* Q3 I% q4 L1 K, ?
while(s[top].m+i<5&&!move(top,s[top].m+i))! n& U) `" K, N0 w
i++;
2 d, P. `; u" B5 V$ C$ k } / @' u1 T' w: C4 o
}
- J5 v# S0 o6 {$ e( M6 A" | C( H else/ b* o- S7 d j
{* F) i( o' Q' V Z8 P/ u
top++;
. w5 j) A4 O3 `6 u* n //在上次状态基础上准备做move4 Y- k( ?3 Z4 z3 |5 q
s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;/ O; O7 a( [" b4 G
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;& s! J6 Q: Y% q' R: l# \! d
i=1;' a5 j& N; A. |! g8 d
while(i<5&&!move(top,i))3 G- N b/ j+ p7 _: G7 q/ @
i++;- b7 h9 x+ M1 d$ s
} - L( [. \ T/ G
}& y8 i! z) C# t% ~* @3 l% T
else
& c/ ]7 s" F) e {- v) {/ R) L) M4 g9 |
//回溯
, Y3 K* U, J! T% m) a- p while(top>=0&&s[top].m>=4) $ y0 s7 q& k! A, ]/ q& r
top--;
F s$ M' Q$ I) Y- d if(top>=0); B- i* A' b8 h+ H- U
{
; l; ^: x0 ^: p2 V$ o/ T! Z //在上次状态基础上准备做move
) H I+ \! S" M6 d, A. j7 R! S- U s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;0 c" y8 v1 A* ^( q' b
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;0 r+ P; W% s/ r$ z6 k
i=1; + W, D. \8 i' P& g$ F! L
while(!move(top,s[top].m+i))
/ x3 Z3 c; T/ e1 m0 _/ [* J i++;% A g- A7 r9 H6 i( Z
}
# m" K$ G4 O. r }
G" B0 O; h4 M3 V- N# b e1 G }//while6 ?# d" Z, A; s `
}//f22 {9 u1 j* O! x3 Z( Z: a
//---------------------------------4 C( ?$ E" i M5 h
|