|
渡河问题
4 P. |* l9 |- a A/ U* Z0 y- S 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? ; I& T2 c# m. r J# ?. T; _
& ~. G& L6 U) o4 F( b程序代码: % P( @" N" O, k% _" U4 D0 r
//以下程序在Win98+vc6.0运行通过
" @8 A2 _( l! T3 U$ m#include <stdio.h>
% `# y7 K& Z& V9 X. o#include <stdlib.h>
) J' i5 h9 r. R- M7 N#define MAX 50. T1 r9 l) k1 n3 Z
struct state1 g& n# R8 U5 b. a. r f5 N( ^; e. b
{3 y8 b* I6 @4 ]% i; F$ w+ i! w* `* D
int man,sheep,wolf,cabbage;//0:在起始岸;1:在目的岸
X5 ~ O a/ R int m;//所采取的过河方法,(1--4)3 Y n, `% r* F: w R
}s[MAX];
5 T3 K; U0 F9 I; ~int count=0;8 B' k7 Z- _6 \4 v0 I+ j
FILE *fp=fopen("c:\\2.txt","w+"); . J0 C+ `' [ x" v
void main()
8 x0 T; f- J/ [5 g- j( Y7 p1 n{9 T, k2 P, f5 k& z1 d
void f1(int ),f2();//f1试探递归
0 v5 g+ \' M0 k. Z s[0].man=s[0].sheep=s[0].wolf=s[0].cabbage=0;
C7 j+ d, }" ~: ~0 S; k. r s[0].m=4;
/ g& v8 _ c) Q& Q; H; S& V- Y- x s[1].man=s[1].sheep=s[1].wolf=s[1].cabbage=0;
7 j$ k4 p) \% h% G( B% r! _) w9 e! {; v f1(1);
5 I/ F8 r" N# T: M //f2();
6 a8 S% t! Z8 {/ ] fclose(fp);' h3 w" |" B3 b
printf("\n"); 9 B2 r! n1 ?7 F M, H1 Q0 c
}
5 p: z& G* @1 t//用m值决定的方法渡河,成功返回1,否则返回0
; y% y$ S/ L8 T: \int move(int top,int m)
! o ]) ^# \. V" f6 Y% }; ?{
; B5 L0 ^0 v" `& |- ^ switch(m)
8 T3 ^0 P; _. }* ?3 K" m) v {$ x4 }- n. r7 s* f# E
//人带羊过河- c$ s/ ^9 {- O3 P$ r
case 1: & t. _. O* w7 N% v; q
//判断人羊是否在同岸9 L9 F) W! R: j8 \* x X5 ^( W
if(s[top].man!=s[top].sheep) : ~6 p$ t4 D7 x) C5 \3 i
return 0;0 |( ?, @! ]7 c# h" M7 s
s[top].sheep=s[top].man=(s[top].man==1)?0:1;% c- f# Z8 {5 K7 \
s[top].m=m;//存储过河方法
7 N, J* V* t- q3 [& P! I break;2 C8 M$ w6 N, A9 _
case 2:
- K. G8 v) n8 ~/ I; ]* l if(s[top].man!=s[top].wolf)) I% `9 D( \: F [: p/ V% a
return 0;
7 S4 U6 x9 i( c; F, t5 h9 q9 K7 a# R s[top].wolf=s[top].man=(s[top].man==1)?0:1;
( l3 D* J. v* T& J+ t6 i s[top].m=m;//存储过河方法
# D: L: m. c3 I break;3 _) \/ _ j @! ?% i1 t# E7 b
case 3:: t& K/ g z) H7 A4 b& \
if(s[top].man!=s[top].cabbage): Y( m9 t1 S5 {9 T# c& e
return 0;
6 H% J( `$ W, O: q8 l s[top].cabbage=s[top].man=(s[top].man==1)?0:1;4 X% g3 m7 a# t8 w8 y
s[top].m=m;//存储过河方法, Y9 o$ O' z/ k, R0 ~
break;
% ^, r$ X0 N& s# R; E' E //人单独过河, U$ p k! S! r& p G
case 4:
. [6 b# G4 E) g3 p$ B4 G7 B f s[top].man=(s[top].man==1)?0:1;
6 M- x9 e" y! b s[top].m=m;//存储过河方法1 G% k; B8 r8 W+ ^: A1 P1 y
break;9 a. B) X8 I: o4 R- B& _
}//switch* H6 N9 H+ t' i0 K0 D: T$ _
return 1;
4 ]6 Q+ t: [: \, p( F0 b}//move8 l: G! Y z) M. b Y
//打印过河步骤
. u0 s6 [$ \ Evoid display(int top); {5 |4 |; b- f( q4 j5 O
{; K L2 r0 r2 U1 S# ], i6 y$ V( o% ?1 q
int i=0;( E% P0 W# _, j: P( C( v* s7 E6 B% T
fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage);
" J: K) h8 L; e4 g for(i=1;i<=top;i++)1 B8 k- ?6 e9 J. E, |
{ Z% u8 a' W9 ?' q3 |5 C% |
switch(s.m)
; _, a" f6 a% x: n' _/ A {
( }) G$ |) C- r3 f W6 b case 1:, b9 \% W# l; |" ?' _
if(s.man==1&&s[i-1].man==0): m8 I6 }4 a! \
fprintf(fp,"人带羊从起始岸过河到目的岸\n");
8 K/ i+ Q/ y' R else
4 V5 j8 {& U# g$ k5 C/ U# o" h fprintf(fp,"人带羊从目的岸过河到起始岸\n");
$ `; j# r' h" j4 ], p break;0 ]% q' |8 x; ]4 W* g
case 2: F4 S2 p1 _; L' l
if(s.man==1&&s[i-1].man==0): I1 X3 i b$ C( \7 B
fprintf(fp,"人带狼从起始岸过河到目的岸\n");
0 ~2 M: q' l! { else5 E2 t/ h/ \# L- z- M B# ?0 M8 w3 h
fprintf(fp,"人带狼从目的岸过河到起始岸\n");
) O9 P& H9 _' [$ f( j9 A- _ break;
% x. @, j$ Y' M' o0 u* {; M; O( G( n, h case 3:) L0 i- Q* D) ?, m' w7 u
if(s.man==1&&s[i-1].man==0)/ d' d+ L4 ^# R a2 G
fprintf(fp,"人带菜从起始岸过河到目的岸\n");' d3 e @' q6 m- ~7 n" d
else9 g+ q8 ^1 K( @
fprintf(fp,"人带菜从目的岸过河到起始岸\n");
7 S. v* G; c j8 ]& \8 b break;9 `- P) @) M7 ]! u. K! X
case 4:
! E2 W, K1 Q8 J3 a4 n% z X: n, } if(s.man==1&&s[i-1].man==0)) N# g) D* Q6 I% z
fprintf(fp,"人单独从起始岸过河到目的岸\n");
: A. a% Q4 f9 Q6 v& {: g else5 w. N' H2 v9 F# U7 C) j: Z# Z
fprintf(fp,"人单独从目的岸过河到起始岸\n");
4 P a: @: f: [& |5 f& N break;
- b4 l* r" q" [! Q4 V; J1 K }//switch, j. N0 Y+ w0 r5 D, x! S/ _2 X
fprintf(fp,"state%d: man: %d, sheep: %d,wolf: %d,cabbage: %d\n",i,s.man,s.sheep,s.wolf,s.cabbage); h1 ^% S4 W- L
: Q; j3 Y2 j. |9 U) C# j+ i
}//for8 a8 T5 T9 R7 P" L7 p; h8 N
fprintf(fp,"All ferried successfully!\n");* z" N; L! E0 @* b3 S
}//display }0 ]$ k- a) D) `3 X
//检查两岸合法性已经有无状态与历史重复性! m) d) L4 U3 U% T
int check(int top)8 D3 S4 ? N' q' W' T1 u- W5 ^9 b
{+ ?8 Y! `0 I. N3 u( C+ A
int i;
0 E$ A! N; J9 A. [9 y* ^! n//检查两岸合法性5 Q' z' a/ y1 Y6 w
if((s[top].sheep!=s[top].man&&s[top].cabbage!=s[top].man)||! Z! K' ]9 P% W; a/ x3 X
(s[top].wolf!=s[top].man&&s[top].sheep!=s[top].man))
5 W/ y1 C- d8 p2 Y8 m return 0;
X( Y4 m5 S7 p1 n1 T& j //检查历史重复性
2 }7 v& A8 D, \. v0 P: A* j4 @4 B3 W for(i=0;i<top;i++)" U, w$ {3 [0 g3 G, B- T+ N' U3 M& b
if(s.man==s[top].man&&s.sheep==s[top].sheep&&s.cabbage==s[top].cabbage&&s.wolf==s[top].wolf)
- T$ U* u& w W2 |; G5 t! @% A( @ return 0;- t9 Z0 w8 |- w1 k. P
//ok$ ~- d2 w' E$ U6 q9 e {
return 1;
6 M! i; y9 K- n! `3 s0 H* o}
7 Z" K. E" z4 b4 Hvoid f1(int top)
6 s4 h2 l% W7 t8 k6 }% J{
! g1 C: L# u( u. j int m;8 E0 ~+ j" F* k* I
if(top>0)//0状态(初试状态应该是预先设置好的,所以要做状态1,故,初试top进来应该是19 [8 j [7 }$ h2 m- L$ U+ I
{ //对每次状态分别试探4中方案
2 h i' C9 H- O( { V for(m=1;m<5;m++)& R& l3 \+ A- b; b; {
{& c0 ^6 Q9 v- c6 Q$ P9 H
//每次方案的实施是在上次结果状态上做的- G' N! G! @/ W) f3 h$ Q
s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;* |% Y( i" t7 @( Q& M0 ]$ o6 E
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;
4 s M! J8 y. c$ ` //用方案m移动,同时检查结果( y. S0 O! f& v* O7 `" g
if(move(top,m)&&check(top))
/ E d! Q5 V) k9 a; O, c {) u8 A: }& Q8 Y7 C1 W; U
if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
; D; j4 c: _% t6 ]7 d! b6 j8 }/ o { Q7 }- p' \( {9 G6 N
//打印渡河步骤, S ~$ ~9 O% J1 ?" R4 [9 l
display(top);
, L2 P9 D1 `# ^; q: K //统计方案个数
8 M3 W# W& V4 b: P count++; ; Q* z& ^9 \/ Z: A
fprintf(fp,"count=%d----------------------------\n\n",count);
8 C& V* c) R9 R' n, @3 P0 ? if(count>1000) exit(1);
# P- ]; s% S# s }
6 `% e6 M) f9 \5 i else
1 e m* F; G) b& _3 ? f1(top+1);
/ z4 ?) q5 M- l5 _% B }
, i4 Q' G/ ~! [ }//for
$ L, P- Z$ M& j& D: @2 Z" u }//if(top>=0)
$ g9 n2 a, p: a+ l9 ?% o4 {7 }6 O}//f1
1 B7 L9 v) y0 U( G
8 @/ e: ^$ h, S2 d& \" z & W% w) D3 ~- _8 [* N
9 |/ v# D; e1 B6 R' @# |void f2()
! b8 q" X# d3 g. m( x{
# V$ U* g' I* h/ H int top=0,i;4 j* p/ ^# b1 ?- b3 I* R
//开始时都在起始岸
% a0 @$ J9 p+ n; ?8 { s[top].man=s[top].sheep=s[top].wolf=s[top].cabbage=0;
( Y+ r- D" V, v4 V; ~8 V //未开始渡河( T% [% m1 k5 i8 Q3 D9 U
s[top].m=4;
/ X% f0 f8 Y$ @: S) H1 w while(top>=0)* W; O# A% g9 t! l/ H
{8 s% h( f- [% p( H" P7 o @
if(check(top))
, L& \. M# G, W# V1 V; x% T( \ {
{1 s1 g" a. a; Z# v4 Q* C- a& f) g if(s[top].man&&s[top].sheep&&s[top].cabbage&&s[top].wolf )
2 W1 [7 ]1 B0 s+ F5 c# f {
1 ^$ r& O6 V* ] //打印渡河步骤
0 U! l8 M ]" l. C display(top);. e% k0 { Q* \1 P2 R
//统计方案个数
% l/ q: v% D% w7 D8 Z count++;
" M0 |. A8 t* p j. w- z fprintf(fp,"count=%d----------------------------\n\n",count);7 [2 E2 u# T$ q( u
if(count>1000) exit(1);
) [; a% ^9 ] V# P9 h. l# a$ \ //回溯
& Q* R# ^- Y/ M while(top>=0&&s[top].m>=4)
( U& k% c$ y" ~& _! ~( N8 D9 o" } top--;
4 g! Z& I( ~' j1 N- l1 t if(top>=0)
3 ^. a4 C( I4 b {3 c& B3 A- Z; X1 f
//在上次状态基础上准备做move$ V! [& T! j. w
s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;( L. A: m0 n/ g) a* R9 A
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;
5 i u( F% L7 C& _. w i=1;
; B& i+ o. V" A1 ?3 L% k while(s[top].m+i<5&&!move(top,s[top].m+i))
0 {9 z, ], m2 r* m! a4 H9 |6 M* w i++;
' ^: e! ]7 q9 q6 |0 b( v. l3 N }
9 p5 w% S" N$ \, Y5 f1 D }8 w0 ?2 l/ C$ i7 d0 v7 ^/ \
else
0 R1 a Q/ D' x, K: R/ M {
6 G) Q0 c5 w- f5 L6 T3 J. M top++;4 h3 `% q( M2 B3 V5 \# h4 {# e
//在上次状态基础上准备做move
0 i# \& |9 b5 n# b3 x s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;+ P6 p% \- t1 k' w
s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;* ^- E( `; k6 x: u+ B% w, [+ [: `
i=1;
2 W5 v0 h2 k/ [, Q2 l( H5 i) u while(i<5&&!move(top,i))
- Y5 m' | e( @# u$ Q" `4 n i++;
+ f0 n7 n9 J6 D, d' F# A }
- B9 [# Y! n$ h; \* ~6 P I+ l }
2 Q- q0 m8 W! {' O else- `* v: T" H! a6 @3 I
{ y5 Y- ]+ a' f2 u
//回溯$ ^; w: E: f1 Y
while(top>=0&&s[top].m>=4)
. [- |$ L0 U P) A( \) A/ L top--;
# B# Q, e1 c, G0 N4 c if(top>=0)
4 J6 \& Y7 {7 R: Y+ ]2 [. `: f9 X& ^ {1 M8 S6 n: ^- O1 H0 A! g
//在上次状态基础上准备做move" W9 F( @2 H( j
s[top].man=s[top-1].man;s[top].sheep=s[top-1].sheep;
; |% [+ F/ ^$ n3 ?" X3 O; k; E& y s[top].cabbage=s[top-1].cabbage;s[top].wolf=s[top-1].wolf;; W- ~4 G* Z! [$ k t- m9 }
i=1;
7 V c8 b" E( ^4 g/ i9 C. V" w while(!move(top,s[top].m+i))5 k+ _# b+ p3 c' b
i++;+ N' @/ m0 a, i, X' D- E. n
} ?) W3 b3 @% `$ v
}0 {: f0 ~" Q9 V4 M
}//while
* j h' |2 B0 ~4 [" ? F+ @}//f2
. I0 Q7 t: {% g6 b+ N( k( u//---------------------------------2 U4 K% n8 i/ Q6 U: ?+ L
|