|
渡河问题 % y4 H& y& m' }' b: g" Y. s8 R4 z; v
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? ( U+ C0 ^. y% E# k& v* u
6 o2 r4 L) y& \3 e程序代码: 1 p: Z7 G C. r( k" z8 ?8 u& u9 E
//以下程序在Win98+vc6.0运行通过
7 S! j* c+ U) D#include <stdio.h>/ I8 R0 t0 ?: L& f# Y/ i2 Q
#include <stdlib.h>0 y+ R& D( t S- ]! n
#define MAX 50
+ M& a8 m) P; o( L7 Y# Z, W) estruct state
2 `% J* @, p+ P& v* N& O8 V{
( W; g7 x6 R& [% Q7 g& `) |& ?# e int man,sheep,wolf,cabbage;//0:在起始岸;1:在目的岸
0 _7 m6 z8 o/ q+ K' `4 b" B) r! b int m;//所采取的过河方法,(1--4)
# t( T/ U+ w9 a: X0 b: ]& A* s6 K}s[MAX];2 O& K' U+ ]/ X# z" S9 A: y
int count=0;4 n9 V/ }7 R3 `
FILE *fp=fopen("c:\\2.txt","w+");
R8 ?$ D$ E3 _7 Ovoid main()
* W' G2 s$ i- R- @$ d( C# P# d3 e{/ G7 o j* C7 ?; J8 A
void f1(int ),f2();//f1试探递归3 N- m' u, }1 Z# U' H/ a' H2 k
s[0].man=s[0].sheep=s[0].wolf=s[0].cabbage=0;
4 G; {, z5 Z, Z$ m( e s[0].m=4;
# @/ k% C: I6 o, y; | s[1].man=s[1].sheep=s[1].wolf=s[1].cabbage=0;
. }( G$ p% U2 \8 q f1(1);
" d% b1 S# m( k" R //f2();2 t. o2 r' ?2 M
fclose(fp);
* x' F. G: j% c! a9 h$ z printf("\n"); 4 s. V( R- S) b: [6 v
}
0 \' p# G. J4 P//用m值决定的方法渡河,成功返回1,否则返回0: A% y6 ?% @9 }5 B8 k
int move(int top,int m)
* r" O3 a$ O* w$ v! w{
0 d, J/ D" B- G: ]5 w$ j$ T d switch(m). G) D: a! t4 w; r5 C
{
: t& U; F, O7 S& { k! Z1 ]% l //人带羊过河
: B% a5 a/ j! W3 v! o+ @) s case 1: 7 j6 a' U4 F, \0 V0 f L
//判断人羊是否在同岸: f; K0 s, F2 n; b0 Q
if(s[top].man!=s[top].sheep)
! s. D' C. E" t8 i6 m2 C: [ return 0;& }/ }- Z' V6 M. J0 N' a6 D
s[top].sheep=s[top].man=(s[top].man==1)?0:1;
4 q" p* H+ W$ Q4 Z8 s s[top].m=m;//存储过河方法
% L9 q! v' r$ X0 h break;- H i/ ~( x5 }
case 2:; H' k$ ]# i2 n* H. R6 Q$ u( }
if(s[top].man!=s[top].wolf)
& Q6 q1 }# R& `! ], g return 0;
7 G U+ C, U5 i) b- O s[top].wolf=s[top].man=(s[top].man==1)?0:1;9 I6 p! b' `/ @( y" W
s[top].m=m;//存储过河方法5 M5 [' `8 E# m& J, y5 _" v. W
break;
% F0 H; t$ p& f5 v7 y E( ? case 3:8 f6 C3 ^3 O, O# }
if(s[top].man!=s[top].cabbage)
" M+ p+ n6 p8 ]% Q0 f8 S4 _5 A8 ` return 0;
* N) A& ?7 x/ Q- u s[top].cabbage=s[top].man=(s[top].man==1)?0:1;. o) ?* W; F% ~% L: m% f
s[top].m=m;//存储过河方法
- @2 ?9 |6 K e! S1 e break;
. j) b0 z3 Q% x! F" R //人单独过河! A& ~9 H$ x& E: h0 m. _ V
case 4:- U2 H9 R& \. Q
s[top].man=(s[top].man==1)?0:1;" M, A0 V- \) y$ K! s
s[top].m=m;//存储过河方法: b- z# n3 G8 Z
break;
" R2 z& t% W' ?; @2 h/ n# s }//switch
; k$ }+ i& A) A3 x+ U' D) W return 1;
) j2 r7 m3 z: m; [}//move1 ~3 t% Q) V$ t/ D. ^
//打印过河步骤3 y0 |) R- D3 D6 |- z5 m1 D/ `5 ] x( z
void display(int top)
2 }6 _9 p3 h- r# b{; X, {4 X H8 U9 Y: I" t
int i=0;: {, y# V7 L/ o9 y6 k
fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);
! I8 w* ^& m e/ i for(i=1;i<=top;i++)
* U" A7 U& r1 S& \) W {
% c! e' m6 V) ]9 z Z2 I switch(s.m)( I7 P5 e" R: Y
{% I6 e! i4 j# @* r6 x
case 1:0 ~! D) d( K& P# v5 ^) M5 k" X
if(s.man==1&&s[i-1].man==0)+ z7 w1 ?" |, W% ^
fprintf(fp,"人带羊从起始岸过河到目的岸\n");
* A, ~( F3 |" X# Z5 v else
* U, L, t, V- X" R" c1 d fprintf(fp,"人带羊从目的岸过河到起始岸\n");
( J3 E9 ]+ {( e' W$ e2 I( S' C break;- X" @# C4 _* K+ c( ?
case 2:
- h: m4 _( ^* g% U if(s.man==1&&s[i-1].man==0)
' Z6 K( u: e$ u) v fprintf(fp,"人带狼从起始岸过河到目的岸\n");( ?+ a. B; [6 s% I* ~# U
else' ^6 G Y4 u8 V
fprintf(fp,"人带狼从目的岸过河到起始岸\n");
' j. _: |/ }: k4 \+ A/ E break;4 I6 ]( D q2 G7 p4 g/ t
case 3:
- w( V [! ?, |0 f if(s.man==1&&s[i-1].man==0)
$ y; V0 j% N) ^ fprintf(fp,"人带菜从起始岸过河到目的岸\n");- O3 L7 l0 p, S9 t2 o3 l
else4 r, j" \0 }* h+ ]; v
fprintf(fp,"人带菜从目的岸过河到起始岸\n");
" w' x ^+ E% X: W ^; A1 ?5 e9 R1 Y: _ break;
% ~ A3 {- F& c) m case 4:
4 V5 ?, H9 ]& I/ C3 | if(s.man==1&&s[i-1].man==0)* b7 W) i4 ^' [1 Q/ P
fprintf(fp,"人单独从起始岸过河到目的岸\n");
5 x- ^" N& a/ A7 {" c K' z else
. t$ \0 ^' ^2 l: `- m5 O fprintf(fp,"人单独从目的岸过河到起始岸\n");) k4 |5 I1 Y4 ~* {; S9 x
break;$ p" n" d. t% L7 _9 [( {
}//switch
" _& x5 ]6 l+ v9 V+ X fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);
' {* D& U, ~6 y9 L % f, i0 B* ]: [
}//for
/ Y4 ]" z2 l! E) C! ]2 y/ efprintf(fp,"All ferried successfully!\n");. l& o5 H6 d; t2 \
}//display
3 m+ A; `& B! q//检查两岸合法性已经有无状态与历史重复性
; ]& Y- c5 Z4 I% y$ Q! R3 ~int check(int top)0 s# ^8 j5 \6 Z2 S) k& X- N
{ u* k3 [# s A0 M2 _, @$ c3 ?) H" C
int i;, ]: [7 r* l- x6 B+ S( m2 C
//检查两岸合法性
6 S/ M7 X: Y2 r if((s[top].sheep!=s[top].man&&s[top].cabbage!=s[top].man)||
+ r" @$ x) P3 `! G) K2 b. b' P (s[top].wolf!=s[top].man&&s[top].sheep!=s[top].man))
; |# j! w4 o% y7 j* P return 0;% J+ t$ j6 W7 R6 E: r5 |. a
//检查历史重复性: b9 C5 i. N0 |4 S" Q6 K
for(i=0;i<top;i++)
1 ^: C5 z7 L# X if(s.man==s[top].man&&s.sheep==s[top].sheep&&s.cabbage==s[top].cabbage&&s.wolf==s[top].wolf)
# e, ~ m0 u. S+ J7 }- g% B2 T return 0;+ P+ i, d* q n0 F
//ok3 `/ Q" R+ q9 y* R9 [; N& k6 e
return 1;
' `0 }6 k% {) g( e( T}
$ h3 J8 J. q- [ b% a% Bvoid f1(int top)6 r9 c9 }) |4 p8 z) x& G) e& O
{ W6 i; G( X& g7 u. S8 B. C/ I- t; m6 @
int m;
& k% d, N9 k" b( N if(top>0)//0状态(初试状态应该是预先设置好的,所以要做状态1,故,初试top进来应该是1
) x' H! N) h( _6 Z { //对每次状态分别试探4中方案7 R7 W6 E9 Y! A! w C* Z( q6 z7 k
for(m=1;m<5;m++)
7 u" a" i; _* x8 u, d {
/ G+ S0 x7 D G; ]) k% ~0 A! G' _ //每次方案的实施是在上次结果状态上做的
3 U' V' f6 K! K5 q s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;- X1 _0 w2 q9 M- S/ }
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;) r2 ]( j8 Y& m; C# P/ M
//用方案m移动,同时检查结果
5 K1 c* K' J5 @8 W% i if(move(top,m)&&check(top))- t$ \5 C6 n3 r3 z1 {( ^6 W
{8 q; e* X9 x8 w7 P
if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
% N: d9 D2 l. Y {
0 d, U2 _$ H$ F7 H9 J g% e8 x1 x& s //打印渡河步骤
( D+ a+ D) h! v/ t) U ] display(top);
% O) z2 \& G4 S, _$ h# V //统计方案个数% V* X0 N9 N6 P/ F# K
count++;
- G. |# O, U6 X0 d( |8 d" s fprintf(fp,"count=%d----------------------------\n\n",count);. H& K9 d; F, V. ]6 {0 F! ]
if(count>1000) exit(1);' J& s9 E4 Y! a# M
}
+ K8 L: Q& @1 {' d8 T else! \, K6 ?' t" I, i+ I+ q9 H2 w
f1(top+1);
7 e5 s+ n; S6 ?7 @2 P }
! l4 y. u8 R# u: B# u/ B, V3 ^ }//for# v! J1 `( I8 I `# b7 ^% m
}//if(top>=0)& l7 x+ F7 r& @' E' k/ {; i* \( I0 m
}//f1 / f3 W. v( I2 b) l! d
' J o2 j/ ^! j* [( K
6 F) {3 h, {% V& R* I; w4 k6 W- F* [
q* a8 w1 l2 N2 |! b& k( vvoid f2()
& [* G& U0 l3 c{/ _4 Y: |& ~, ]( K; ]) l
int top=0,i;
6 o O4 Y) B0 `; ?0 B* ~( \ //开始时都在起始岸; I o/ T2 b6 g* N2 c
s[top].man=s[top].sheep=s[top].wolf=s[top].cabbage=0;, _( r. O$ e( n- [* V
//未开始渡河$ l* ~& W% o# B# X* ~$ _
s[top].m=4;
+ P: {: W- S9 X6 e while(top>=0)
: k0 `$ c& ~) \6 C+ J$ Q {8 ^, z* I' o8 x- O; f7 Y
if(check(top))& k3 v0 D. p x7 J6 Q1 L0 Y1 d
{
9 t' e- f: |. l if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
/ j/ g' L. q" Y4 f% Z( ^ {
" J$ W4 W5 }3 f8 ] @ //打印渡河步骤2 @* Q/ w. s G
display(top);' l1 m# h" Z1 Y4 ~! G7 |! C6 g
//统计方案个数
! u( J5 `/ d) |" H0 ]8 N6 D! j count++;
) U! Y2 R7 f% Q$ H$ k) ]. U9 c fprintf(fp,"count=%d----------------------------\n\n",count);" I! L+ M0 \5 Z: _
if(count>1000) exit(1);: Y( d) N+ B9 n
//回溯+ ]5 q, ]6 o# d0 p1 j. J. f" n
while(top>=0&&s[top].m>=4)
" i1 [) C B" x$ ]* j, O! Q0 L ? top--;( m1 O6 o) a& s5 Q
if(top>=0) x' i2 D* b. {3 o
{
3 j7 S% E1 H, W: X0 b9 ^6 h //在上次状态基础上准备做move
. {3 d' p% U) `' S0 X+ T8 F) u$ o s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;
! }% _: W1 F {/ t* W/ G! \0 [% Y1 Q s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;3 {% q( m# E$ |6 Z5 @3 M
i=1;! @% B% n) N1 s: P
while(s[top].m+i<5&&!move(top,s[top].m+i))
+ e: x6 @; `5 x) T9 c$ H2 V i++;: f1 R$ R6 f( q" N% J$ {5 x f
}
* S" ^+ l) k# J8 r) e T. D N }
+ u6 a# ?4 D2 V4 b else
" s: ]3 h/ B4 r& [ F. S, Z S! O {& Q* h. v4 w1 Y0 s
top++;# a/ t" H. H2 z8 B" R
//在上次状态基础上准备做move
& h0 |0 N& w" t9 { s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;3 `) F2 y* x+ _1 \$ d8 S1 |" J, r
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;
# r2 r$ {8 L; p- Z5 a. l: d i=1;" b/ y: V5 B4 o! J, S+ t
while(i<5&&!move(top,i))
' O4 q" U: a( ]3 U1 N G$ K+ U i++;1 K8 _* N( t6 h, [7 v
} 0 P5 {6 L3 t& c* X
}# n) b9 V8 h% W' C
else& w% O: s( {$ p; u3 C! ?9 G& J
{
8 r( }" @1 w. g; R0 ]' V //回溯
B9 {4 w0 v! m3 Q) b while(top>=0&&s[top].m>=4) : t. H$ `% y! {+ [
top--;
6 p. K& o0 w5 D K! M' ` if(top>=0): W6 K$ [' m5 O$ T) X1 s
{9 d0 G1 n) @* `% @4 a
//在上次状态基础上准备做move
5 t" \7 @2 C2 I4 f: }8 Q0 A s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;5 H2 a" k8 m- o: M3 v% X
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;
# C) d, O: D' r0 p6 c i=1; ( I, p" |' ]- n; s/ C4 T4 j1 [
while(!move(top,s[top].m+i))
7 z& V$ z% s0 D, a& V4 d O0 J3 t i++;2 a1 [' P. e. a9 N8 x- D
}( @3 W5 K* f+ _- Z# A/ q$ E
}
/ S& `7 u8 R' q3 f3 W }//while
* ~4 z% m$ J6 q$ A}//f25 J* N, I( Q. y
//---------------------------------
1 r* z% ~# m; I3 ^ F H |