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

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

 

 

 

/* 
    四个字段分别代表 羊,狼,草,人的位置,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 

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

 


/* 

    前五个字段分别代表 左人数,左鬼数,右人数,右鬼数,船位置 
    船位置为代表在右边,代表在左边 
    当右边没有人和鬼时(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人鬼过河→人返回→鬼过河→鬼返回→人过河→人鬼返回→人过河→鬼返回→鬼过河→人返回→人鬼过河→ 
*/ 

 

 

 

/* 
第三关:一家人过河 

结果:过河的全部组合有万多中情况,其中满足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  ,  @t b ,  @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  ,  @t b ,  @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行 
*/ 

 


/*第四关:跳马 
*/ 

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 ))
)
select p  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行 
*/ 

 

 

; 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上→ 
*/ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星火燎猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值