SQL递归游戏-你厉害吗,来过5关

5个flash的游戏地址是
http://www.sostart.com/article/view.php/765
此类游戏一般都是通过穷举或者递归之类的方法来求解,对于编成语言来说都比较简单。
这里用SQL语言的CTE递归来玩玩看。我的算法和答案如下:

SQL递归游戏-你厉害吗,来过5关

/*
四个字段分别代表 羊,狼,草,人的位置,0表示河左边,1表示河右边。
每次都必须有人过河,因为动物和植物们都不会划船。
*/
declare @t table( y bit , l bit , c bit , r bit , path varchar( 8000))
insert into @t select 0 , 0 , 0 , 0 , ''

; with t
as
(
select * , 0 as cc from @t union all
select ~ y , l , c , ~ r , path + '人羊' + ltrim( r) + '→' , cc + 1 from t where cc < 10 and y = r and y & l & c = 0 and path not like '%人羊_→' union all
select y , ~ l , c , ~ r , path + '人狼' + ltrim( r) + '→' , cc + 1 from t where cc < 10 and l = r and y & l & c = 0 and y <> c and path not like '%人狼_→' union all
select y , l , ~ c , ~ r , path + '人草' + ltrim( r) + '→' , cc + 1 from t where cc < 10 and c = r and y & l & c = 0 and y <> l and path not like '%人草_→' union all
select y , l , c , ~ r , path + '人' + ltrim( r) + '→' , cc + 1 from t where cc < 10 and y & l & c = 0 and y <> c and y <> l and path not like '%人_→'

)
select REPLACE( REPLACE( path , '0' , '过河' ), '1' , '返回') as path from t where y & l & c = 1

/*
人羊过河→人返回→人草过河→人羊返回→人狼过河→人返回→人羊过河→
人羊过河→人返回→人狼过河→人羊返回→人草过河→人返回→人羊过河→
*/

SQL递归游戏-你厉害吗,来过5关


/*

前五个字段分别代表 左人数,左鬼数,右人数,右鬼数,船位置
船位置为代表在右边,代表在左边
当右边没有人和鬼时(gr+pr>0),不执行返回操作,递归结束
*/
; with t( pl , gl , pr , gr , boat , path)
as
(
select 0 , 0 , 3 , 3 , cast( 0 as bit ), cast( '' as varchar( 8000)) union all
select pl + 2 as pl , gl , pr - 2 as pr , gr , ~ boat , path + '2人过河→'
from t where boat = 0 and pr >= 2 and( pr - 2 >= gr or pr = 2) union all
select pl + 1 , gl + 1 , pr - 1 , gr - 1 , ~ boat , path + '1人鬼过河→'
from t where boat = 0 and pr >= 1 and gr >= 1 and pl >= gl union all
select pl , gl + 2 , pr , gr - 2 , ~ boat , path + '2鬼过河→'
from t where boat = 0 and gr >= 2 and( pl - 2 >= gl or pl = 0) union all
select pl - 1 , gl , pr + 1 , gr , ~ boat , path + '1人返回→'
from t where boat = 1 and pl >= 1 and gr + pr > 0 and( pl - 1 >= gl or pl = 1) and pr + 1 >= gr union all
select pl , gl - 1 , pr , gr + 1 , ~ boat , path + '1鬼返回→'
from t where boat = 1 and gl >= 1 and gr + pr > 0 and( pr - 1 >= gr or pr = 0) union all
select pl - 1 , gl - 1 , pr + 1 , gr + 1 , ~ boat , path + '1人鬼返回→'
from t where boat = 1 and pl >= 1 and gl >= 1 and gr + pr > 0 and pr >= gr and path not like '%1人鬼过河→'
)
select path from t where pr = 0 and gr = 0

/*
2鬼过河→鬼返回→鬼过河→鬼返回→人过河→人鬼返回→人过河→鬼返回→鬼过河→鬼返回→鬼过河→
2鬼过河→鬼返回→鬼过河→鬼返回→人过河→人鬼返回→人过河→鬼返回→鬼过河→人返回→人鬼过河→
1人鬼过河→人返回→鬼过河→鬼返回→人过河→人鬼返回→人过河→鬼返回→鬼过河→鬼返回→鬼过河→
1人鬼过河→人返回→鬼过河→鬼返回→人过河→人鬼返回→人过河→鬼返回→鬼过河→人返回→人鬼过河→
*/

SQL递归游戏-你厉害吗,来过5关

/*
第三关:一家人过河

结果:过河的全部组合有万多中情况,其中满足s之内的有种方法

关联的三个表a b c配合charindex函数分别可以表示出可以过河的两个人和可以返回的一个人
当没有人可以过河则递归自动结束
递归中的case语句可以表示当对岸有个人的时候就不需要返回
*/

declare @t table( name varchar( 8000 ), time int)

insert into @t
select '瘦人' , 1 union
select '小胖' , 3 union
select '姑娘' , 6 union
select '大胖' , 8 union
select '瘸子' , 12

; with t( forword_name , time , path) as(

select replace( a . name +b . name , c . name , '' ),b . time + c . time , a . name +b . name + '过河→' + c . name + '返回→'
from @t a , @tb , @t c where a . time <b . time and charindex( c . name , a . name +b . name) > 0

union all

select
case when len( forword_name) < 6 then replace( forword_name + a . name +b . name , c . name , '') else forword_name + a . name +b . name end ,
case when len( forword_name) < 6 then t . time +b . time + c . time else t . time +b . time end ,
case when len( forword_name) < 6 then path + a . name +b . name + '过河→' + c . name + '返回→' else path + a . name +b . name + '过河→' end
from @t a , @tb , @t c , t where a . time <b . time and charindex( c . name , forword_name + a . name +b . name) > 0
and charindex( a . name , t . forword_name) = 0 and charindex(b . name , t . forword_name) = 0
)
select path , time from t where len( forword_name) = 10 and time <= 30
/*
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人小胖过河→瘦人返回→瘦人姑娘过河→
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人小胖过河→瘦人返回→瘦人姑娘过河→
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人小胖过河→瘦人返回→瘦人姑娘过河→
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人小胖过河→瘦人返回→瘦人姑娘过河→
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人小胖过河→瘦人返回→瘦人姑娘过河→
瘦人小胖过河→小胖返回→大胖瘸子过河→瘦人返回→瘦人姑娘过河→瘦人返回→瘦人小胖过河→
...共40行
*/

SQL递归游戏-你厉害吗,来过5关


/*第四关:跳马
*/

declare @t table(p varchar( max ), x int , y int)
insert into @t
select 'p11' , 1 , 1 union
select 'p12' , 1 , 2 union
select 'p13' , 1 , 3 union
select 'p14' , 1 , 4 union
select 'p21' , 2 , 1 union
select 'p22' , 2 , 2 union
select 'p23' , 2 , 3 union
select 'p24' , 2 , 4 union
select 'p31' , 3 , 1 union
select 'p32' , 3 , 2 union
select 'p33' , 3 , 3 union
select 'p34' , 3 , 4 union
select 'p42' , 4 , 2 union
select 'p43' , 4 , 3

; with t( pstart ,p , c , x , y) as
(
select p ,p , 1 , x , y from @t
union all
select t . pstart , t .p + '→' + t_next .p , c + 1 , t_next . x , t_next . y from @t t_next , t where
(
( abs( t_next . x - t . x) = 1 and abs( t_next . y - t . y) = 2) or
( abs( t_next . x - t . x) = 2 and abs( t_next . y - t . y) = 1) )
and( CHARINDEX( t_next .p , t .p) = 0 or( c = 14 and t_next .p = t . pstart))
)
selectp from t where c = 15

/*
p43→p31→p23→p11→p32→p13→p21→p42→p34→p22→p14→p33→p12→p24→p43
p43→p31→p12→p33→p14→p22→p34→p13→p21→p42→p23→p11→p32→p24→p43
p43→p31→p12→p24→p32→p11→p23→p42→p34→p13→p21→p33→p14→p22→p43
p43→p24→p32→p11→p23→p42→p21→p13→p34→p22→p14→p33→p12→p31→p43
...共112行
*/

SQL递归游戏-你厉害吗,来过5关

; with t as(
select 17 as f1 , 26 as f2 , 20 as f3 , 19 as f4 , 31 as f5 , cast( '' as varchar( 8000)) as path
union all select f1 + 8 , f2 + 8 , f3 , f4 , f5 , path + '12上→' from t where f1 < 21 and f2 < 21
union all select f1 + 8 , f2 , f3 + 8 , f4 , f5 , path + '13上→' from t where f1 < 21 and f3 < 21
union all select f1 + 8 , f2 , f3 , f4 + 8 , f5 , path + '14上→' from t where f1 < 21 and f4 < 21
union all select f1 + 8 , f2 , f3 , f4 , f5 + 8 , path + '15上→' from t where f1 < 21 and f5 < 21
union all select f1 , f2 + 8 , f3 + 8 , f4 , f5 , path + '23上→' from t where f2 < 21 and f2 < 21
union all select f1 , f2 + 8 , f3 , f4 + 8 , f5 , path + '24上→' from t where f2 < 21 and f4 < 21
union all select f1 , f2 + 8 , f3 , f4 , f5 + 8 , path + '25上→' from t where f2 < 21 and f5 < 21
union all select f1 , f2 , f3 + 8 , f4 + 8 , f5 , path + '34上→' from t where f3 < 21 and f4 < 21
union all select f1 , f2 , f3 + 8 , f4 , f5 + 8 , path + '35上→' from t where f3 < 21 and f5 < 21
union all select f1 , f2 , f3 , f4 + 8 , f5 + 8 , path + '45上→' from t where f4 < 21 and f5 < 21
union all select f1 - 13 , f2 - 13 , f3 , f4 , f5 , path + '12下→' from t where f1 > 25 and f2 > 25
union all select f1 - 13 , f2 , f3 - 13 , f4 , f5 , path + '13下→' from t where f1 > 25 and f3 > 25
union all select f1 - 13 , f2 , f3 , f4 - 13 , f5 , path + '14下→' from t where f1 > 25 and f4 > 25
union all select f1 - 13 , f2 , f3 , f4 , f5 - 13 , path + '15下→' from t where f1 > 25 and f5 > 25
union all select f1 , f2 - 13 , f3 - 13 , f4 , f5 , path + '23下→' from t where f2 > 25 and f2 > 25
union all select f1 , f2 - 13 , f3 , f4 - 13 , f5 , path + '24下→' from t where f2 > 25 and f4 > 25
union all select f1 , f2 - 13 , f3 , f4 , f5 - 13 , path + '25下→' from t where f2 > 25 and f5 > 25
union all select f1 , f2 , f3 - 13 , f4 - 13 , f5 , path + '34下→' from t where f3 > 25 and f4 > 25
union all select f1 , f2 , f3 - 13 , f4 , f5 - 13 , path + '35下→' from t where f3 > 25 and f5 > 25
union all select f1 , f2 , f3 , f4 - 13 , f5 - 13 , path + '45下→' from t where f4 > 25 and f5 > 25

union all select f1 + 8 , f2 + 8 , f3 , f4 , f5 , path + '12上→' from t where f1 < 21 and f2 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 + 8 , f2 , f3 + 8 , f4 , f5 , path + '13上→' from t where f1 < 21 and f3 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 + 8 , f2 , f3 , f4 + 8 , f5 , path + '14上→' from t where f1 < 21 and f4 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 + 8 , f2 , f3 , f4 , f5 + 8 , path + '15上→' from t where f1 < 21 and f5 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 + 8 , f3 + 8 , f4 , f5 , path + '23上→' from t where f2 < 21 and f2 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 + 8 , f3 , f4 + 8 , f5 , path + '24上→' from t where f2 < 21 and f4 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 + 8 , f3 , f4 , f5 + 8 , path + '25上→' from t where f2 < 21 and f5 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 , f3 + 8 , f4 + 8 , f5 , path + '34上→' from t where f3 < 21 and f4 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 , f3 + 8 , f4 , f5 + 8 , path + '35上→' from t where f3 < 21 and f5 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
union all select f1 , f2 , f3 , f4 + 8 , f5 + 8 , path + '45上→' from t where f4 < 21 and f5 < 23 and f3 between 21 and 25 and f4 between 21 and 25 and f5 between 21 and 25
)

select path from t
where f1 between 21 and 25
and f2 between 21 and 25
and f3 between 21 and 25
and f4 between 21 and 25
and f5 between 21 and 25

/*
34上→45下→45上→35下→35上→15上→25下→25上→
34上→45下→45上→35下→35上→14上→24下→24上→
34上→35下→35上→45下→45上→15上→25下→25上→
34上→35下→35上→45下→45上→14上→24下→24上→
*/

你可能感兴趣的:(sql)