返回列表 发帖
好吧,其实我忘了说。。
每个数字只用一次来的。。

TOP

思维稍乱,重新整理了一下
@echo off
set "arr=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79,  1,2,3"
set /a range1=102, range2=105
:main
setlocal enableDelayedExpansion
for %%a in (%arr%) do set /a num+=1 & set a[!num!]=%%a
if %num% gtr 20 echo Are you killing me?&pause&exit /b %num%
rem 冒泡排序
for /l %%i in (1 1 %num%) do (
    set /a start = %%i + 1
    for /l %%j in (!start! 1 %num%) do if !a[%%i]! gtr !a[%%j]! (
        set tmp=!a[%%i]!
        set a[%%i]=!a[%%j]!
        set a[%%j]=!tmp!
    )
)
for /l %%a in (1 1 %num%) do (
    set /a min=0, max=0
    for /l %%i in (1 1 %%a) do set /a min+=a[%%i], n=num-%%i+1&set /a max+=a[!n!]
    if !min! leq %range2% if !max! geq %range1% (
        rem echo %%a:[!min!,!max!]
        call :Combination  %%a %num%
    )
)
pause
endlocal&exit/b
rem 获取组合
:Combination [num] [len]
%static% set letters=[abcdefghijklmnopqrstuvwxyz]
setlocal enableDelayedExpansion
set /a num=%1, len=%2
for /l %%a in (1 1 %num%) do (
    set var=!letters:~%%a,1!
    if 1==%%a (
        set "set_start=set start=1"
    ) else (
        set /a base=%%a-1
        for %%i in (!base!) do set base=!letters:~%%i,1!
        set "set_start=set /a start=%%!base!+1"
    )
    set "do=!do! !set_start! & for /l %%!var! in (^!start^!,1,%len%) do "
    set "exp=!exp!,^!a[%%!var!]^!"
)
%do% (
    set /a prior=sum, sum=0
    if !prior! leq %range2% (
        for %%a in (%exp%) do set /a sum+=%%a
        if !sum! geq %range1% if !sum! leq %range2% echo%exp:,=+%=!sum!
    )
)
endlocal
goto :eofCOPY

TOP

来一个穷举法
@echo off
setlocal enableDelayedExpansion
set "arr=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79"
set /a range1=102, range2=105
for %%a in (%arr%) do set /a num+=1 & set a[!num!]=%%a
rem 冒泡排序
for /l %%i in (1 1 %num%) do (
    set /a start = %%i + 1
    for /l %%j in (!start! 1 %num%) do if !a[%%i]! gtr !a[%%j]! (
        set tmp=!a[%%i]!
        set a[%%i]=!a[%%j]!
        set a[%%j]=!tmp!
    )
)
for /l %%a in (1 1 %num%) do (
    set /a min=0, max=0
    for /l %%i in (1 1 %%a) do set /a min+=a[%%i], n=num-%%i+1&set /a max+=a[!n!]
    if !min! leq %range2% if !max! geq %range1% (
        rem echo %%a:[!min!,!max!]
        call :Arrangement  %%a %num%
    )
)
pause&exit/b
rem 获取排列
:Arrangement [num] [len]
setlocal enableDelayedExpansion
set /a num=%1, len=%2
for /l %%a in (1 1 %num%) do (
    if 1==%%a (set start=1&set "setstart=set start=1&") else (set /a start=%%a-1&set start=%%!start!&set "setstart=set /a start=!start!+1&")
    set "do=!do! !setstart! for /l %%%%a in (^!start^!,1,%len%) do "
    set "exp=!exp!,^!a[%%%%a]^!"
)
%do% (
    set /a prior=sum, sum=0
    if !prior! leq %range2% (
        for %%a in (%exp%) do set /a sum+=%%a
        if !sum! geq %range1% if !sum! leq %range2% echo%exp:,=+%=!sum!
    )
)
endlocal
goto :eofCOPY

TOP

楼主是说>=52吧?
看来思路是大致相同的,主要还是求组合的问题。不过用批处理实现递归,感觉call太多,是不是会影响效率(当然我的代码效率也不见得高)

TOP

楼上说的没错,将(最好是53) 作为分界线,可以减少很多计算。
我说说我的算法吧

1:将数字排序,从小到大。
2:分成2个数字组合,>=53的 和 <53的,才发现我写成了58 =.=。
3:从大到小,循环<53的数字组合,递归调用。每循环到一个数字时,计算当前SUM,如果102<sum<105,则输出。如果<103则递归调用余下的数字。

比如 54321 的数字串,循环到5的时候,下一次就循环4321字串,计算5+4的值,再下一次循环321,计算5+4+3。
这主要是为了防止重复。
因为当计算5+3的时候,就不用再计算5+3+4了,直接5+3+2。
以此类推。 如果当前SUM>104,那么则轮空。

其实从小到大循环是最好的,当较小的数的SUM>104时,后面较大的数就可以不用参与计算,跳过循环了,但批处理的跳出机制问题没有采用。

TOP

本帖最后由 wankoilz 于 2011-5-17 14:33 编辑

楼主能不能说说大致思路,看代码有点累
我来一个比较笨的方法:
将这15个数字分成两组,小于等于51的10个数字为一组,大于51的5个数字为一组。
求出前一组10个数字的所有组合的和,找出符合102<sum<105 组合。
后一组的5个数中最小的也是52,所以任何一个符合102<sum<105 的组合都只可能有该分组中的一个数字。
于是把这5个数分别和“前10个数字的所有组合(上一步已保存)”进行组合,找出符合102<sum<105的就行了。

这方法已经近似穷举了,幸好大于等于52的数字有5个,而使得前面只需要找出10个数字的组合。要如果直接求15个数字的所有组合的话就不知要等到猴年马月了!
@echo off&setlocal enabledelayedexpansion
set str=8, 13, 2,  37, 19, 11, 7,  22, 38
set _51=ok
for %%a in (%str%) do (
    for /f "delims=_=" %%b in ('set _') do (
        set/a sum=%%b+%%a
        if !sum! gtr 102 if !sum! lss 105 echo %%b+%%a=!sum!
        if !sum! lss 104 set _%%b+%%a=ok
    )
set _%%a=ok
)
rem 将后5个数字分别与前面所有组合相组合,并求和判断
for %%a in (52, 61,62, 79, 85) do (
    for /f "delims=_=" %%b in ('set _') do (
        set/a sum=%%b+%%a
        if !sum! gtr 102 if !sum! lss 105 echo %%b+%%a=!sum!
))
pauseCOPY

TOP

算了,我自己放一组代码吧。
@ECHO OFF&SETLOCAL ENABLEDELAYEDEXPANSION
set "sz=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79"
for %%i in (!sz!) do (
      set "array=_%%i_ !array!"
      for %%j in (!array!) do (
          for /f "delims=_" %%k in ("%%j") do (
              if %%i gtr %%k (
                  set "array=!array:_%%i_=#!"
                  set "array=!array:_%%k_=_%%i_!"
                  set "array=!array:#=_%%k_!"
              )
           )
      )
)
set "array=!array:_=!"&for %%i in (!array!) do (
      if %%i lss 58 (
          set /a n+=1
          set "min_!n!=%%i"
      ) else (
          set "_max=!_max! %%i"
      )
)
for %%i in (0 !_max!) do (
    call :loop %%i !n!
)
goto :eof
:loop [next] [cut]
for /l %%n in (%2,-1,1) do (
    set str=%1+!min_%%n!
    if %1 equ 0 set str=!min_%%n!
    set /a v=!str!
    if !v! lss 105 if !v! gtr 102 echo,!str!=!v!
    if !v! lss 103 (
            set /a cut=%%n-1
            call :loop !str! !cut!
     )
)COPY

TOP

返回列表