首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

关于那道趣的算法题:实现24点游戏求解的存储过程,该怎么处理

2012-01-20 
关于那道趣的算法题:实现24点游戏求解的存储过程我也写了一个,跟大家分享一下:)--保存运算符之间的优先级,

关于那道趣的算法题:实现24点游戏求解的存储过程
我也写了一个,跟大家分享一下:)
--保存运算符之间的优先级,通过该表可以判断在一个表达式中加上一对括号是否会改变表达式的值。
create   table   t_operator   (operator1   char(1),operator2   char(1),flag   int)
insert   t_operator(operator1,operator2,flag)
select   '- ', '+ ', '2 '   union   all   select   '- ', '- ', '2 '   union   all   select   '/ ', '* ', '2 '   union   all  
select   '/ ', '/ ', '2 '   union   all   select   '* ', '+ ', '2 '   union   all   select   '* ', '- ', '2 '   union   all
select   '/ ', '+ ', '2 '   union   all   select   '/ ', '- ', '2 '   union   all   select   '+ ', '* ', '1 '   union   all
select   '+ ', '/ ', '1 '   union   all   select   '- ', '* ', '1 '   union   all   select   '- ', '/ ', '1 '
go

create   proc   p_calc_24   @a   int,@b   int,@c   int,@d   int
as
/*
    描述:
        给定任意四个整数,保持数字顺序不变,在数字中间加入+-*   /()等符号,使表达式等于24,括号最多加4-2=2对。    
    版本:
        时间                         修改人     操作
        2007年05月21日     mengmou   创建
    输入参数:
        任意四个整数.
    涉及:
        表t_operator,保存运算符之间的优先级,通过该表可以判断在一个表达式中加上一对括号是否会改变表达式的值。
    返回:
        所有满足条件的表达式的结果集。
    BUG:
        1.表达式[8+13-9*2]⑴派生出[(8+13-9)*2]⑵和[8+(13-9)*2]⑶,表达式⑶又派生出[(8+(13-9))*2]⑷,
            表达式⑷中的内层括号并不影响⑷的值,⑷相当于⑵的冗余,所以像⑷这类冗余不应该出现在结果集中。
            四个整数的表达式最多有两对括号,如果一一列举出所有情况并判断是否为冗余,会使代码会非常臃肿。
*/

set   nocount   on
set   arithabort   off  
set   arithignore   off  
set   ansi_warnings   off

declare   @operator_list   varchar(4),@x   int,@y   int,@z   int,@i   int,@sql   nvarchar(50),@result   numeric(38,6)
    ,@aa   varchar(10),@bb   varchar(10),@cc   varchar(10),@dd   varchar(10),@xx   char(1),@yy   char(1),@zz   char(1)
    ,@id   int,@operator   varchar(8000),@group_id   int,@new_operator   varchar(8000),@min_id   int,@max_id   int
    ,@old_group_id   int,@new_group_id   int
select   @aa   =   convert(varchar(10),@a)+ '.0 ',@bb   =   convert(varchar(10),@b)+ '.0 ',@cc   =   convert(varchar(10),@c)+ '.0 '
    ,@dd   =   convert(varchar(10),@d)+ '.0 ',@operator_list   =   '-+/* ',@x   =   1,@y   =   1,@z   =   1,@i   =   1,@new_operator   =   ' '
    ,@new_group_id   =   1,@old_group_id   =   0
declare   @t_expression   table(expression   varchar(50))
declare   @t_operator   table(group_id   int,id   int   identity,operator   varchar(8000))

while   @x   <=   4
begin
    while   @y   <=   4


    begin
        while   @z   <=   4--增加嵌套循环的层数便可以实现在N个数中间加上+-*/()使表达式等于M,括号最多加N-2对。
        begin
            select   @xx   =   substring(@operator_list,@x,1),@yy   =   substring(@operator_list,@y,1)
                ,@zz   =   substring(@operator_list,@z,1)
                ,@sql   =   'select   @result   = '+   @aa   +   @xx   +   @bb   +   @yy   +   @cc   +   @zz   +   @dd  
            exec   sp_executesql   @sql,N '@result   numeric(38,6)   out ',@result   out
           
            if   @result   =   24.00000
            begin
                insert   @t_expression(expression)   select   replace(stuff(@sql,1,16, ' '), '.0 ', ' ')
            end
            else--去掉else中的代码返回只有加减乘除没有括号的表达式
            begin
                insert   @t_operator
                select   @new_group_id,@aa   union   all   select   @new_group_id,@xx   union   all   select   @new_group_id,@bb   union   all  
                select   @new_group_id,@yy   union   all   select   @new_group_id,@cc   union   all   select   @new_group_id,@zz   union   all  
                select   @new_group_id,@dd
               
                set   @new_group_id   =   @new_group_id   +   1
            loop1:
                declare   c_suited_id   cursor   for
                select   distinct   _a.group_id
                    ,case   when   exists(select   1   from   t_operator   where   flag   =   1   and   operator1   =   _a.operator   and   operator2   =   _b.operator)
                        then   _a.id-1   else   _a.id+1   end   as   min_id
                    ,case   when   exists(select   1   from   t_operator   where   flag   =   1   and   operator1   =   _a.operator   and   operator2   =   _b.operator)
                        then   _b.id-1   else   _b.id+1   end   as   max_id
                from   @t_operator   _a
                join   @t_operator   _b   on   _b.id   >   _a.id   and   _b.group_id   =   _a.group_id


                where   _a.group_id   > =   @old_group_id   and   _b.group_id   > =   @old_group_id
                    and   _a.operator   in   ( '+ ', '- ', '* ', '/ ')   and   _b.operator   in   ( '+ ', '- ', '* ', '/ ')
                    and   exists(select   1   from   t_operator   where   operator1   =   _a.operator   and   operator2   =   _b.operator   )
       
                set   @old_group_id   =   @new_group_id
                open   c_suited_id
                fetch   next   from   c_suited_id   into   @group_id,@min_id,@max_id
                while   @@fetch_status   =   0
                begin
                    set   @new_operator   =   ' '
                    select   @new_operator   =   @new_operator   +   operator
                    from   @t_operator
                    where   group_id   =   @group_id   and   id   between   @min_id   and   @max_id
                   
                    insert   @t_operator(group_id,operator)
                    select   @new_group_id,*  
                    from   (
                        select   operator   from   @t_operator   where   group_id   =   @group_id   and   id   <   @min_id   union   all
                        select   '( '+@new_operator+ ') '   union   all
                        select   operator   from   @t_operator   where   group_id   =   @group_id   and   id   >   @max_id  
                    )   x
                   
                    select   @sql   =   ' '
                    select   @sql   =   @sql   +   operator   from   @t_operator   where   group_id   =   @new_group_id   order   by   id
                    select   @sql   =   'select   @result   = '   +   @sql
                    exec   sp_executesql   @sql,N '@result   numeric(38,6)   out ',@result   out


                    if   @result   =   24.00000
                        insert   @t_expression(expression)   select   replace(stuff(@sql,1,16, ' '), '.0 ', ' ')
                   
                    set   @new_group_id   =   @new_group_id   +   1
                    fetch   next   from   c_suited_id   into   @group_id,@min_id,@max_id
                end
                close   c_suited_id
                deallocate   c_suited_id
               
                if   @old_group_id   <   @new_group_id
                    goto   loop1
                delete   @t_operator
            end
            set   @z   =   @z   +   1
        end
        select   @y   =   @y   +   1,@z   =   1
    end
    select   @x   =   @x   +   1,@y   =   1,@z   =   1
end
select   distinct   *   from   @t_expression   order   by   expression
go


[解决办法]
有问题吗?
[解决办法]
呀~在网吧~~没环境~~~~~~只是对你说的方式不认同!!偶也很不喜欢滥用IF
[解决办法]
偶路过...

[解决办法]
楼主我砍破最有交流,佩服

热点排行