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 = 0union 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上→
*/

 

 

 

厉害吗,来过5关试试?(挑战你的智商!)

07-21

[url=http://www.sostart.com/article/view.php/765]http://www.sostart.com/article/view.php/765[/url]rnrn每个优秀通过sql语句来计算最终得完成路径rnrnrnrn比如第四关的一种解法rnrn[img=http://hi.csdn.net/attachment/201007/21/0_1279725874NuTU.gif][/img]rnrn规则:rn在一个棋盘中棋子的路线同象棋中的马,走"日字"rnrn目标:rn从任意一个点起跳,经过每个格子一次,最终能够回到源点。rnrn棋盘坐标:rn[img=http://hi.csdn.net/attachment/201007/21/0_1279725162SPCI.gif][/img]rnrnrn原理:rn通过递归,在15步之后(一共14个格子,起始点经过2次)回到起始点rnrn算法:rnrn[code=SQL]rn--第四关:跳马rnrndeclare @t table(p varchar(max),x int,y int)rninsert into @t rnselect 'p11',1,1 union rnselect 'p12',1,2 union rnselect 'p13',1,3 union rnselect 'p14',1,4 union rnselect 'p21',2,1 union rnselect 'p22',2,2 union rnselect 'p23',2,3 union rnselect 'p24',2,4 union rnselect 'p31',3,1 union rnselect 'p32',3,2 union rnselect 'p33',3,3 union rnselect 'p34',3,4 union rnselect 'p42',4,2 union rnselect 'p43',4,3 rnrn;with t(pstart,p,c,x,y) asrn(rn select p,p,1,x,y from @trn union allrn select t.pstart,t.p+'->'+t_next.p,c+1,t_next.x,t_next.y from @t t_next,t where rn (rn (abs(t_next.x-t.x)=1 and abs(t_next.y-t.y)=2) orrn (abs(t_next.x-t.x)=2 and abs(t_next.y-t.y)=1) )rn and (CHARINDEX(t_next.p,t.p)=0 or (c=14 and t_next.p=t.pstart))rn)rnselect p from t where c=15[/code]rnrn结果:rnrn每个格子都可以作为起始点,各自有8种解法,一共112种组合。不借助外力能快速完成的人应该具有极高的智商或者及好的rp。rnrnrnrnrnrnrn 论坛

没有更多推荐了,返回首页