返回列表 发帖
来一个穷举法
@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

思维稍乱,重新整理了一下
@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

我知道是这个意思。
set "arr=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79,  1,2,3"
后面故意加了个重复数字

TOP

思维形成定势了,果然有纰漏。稍作改造如下:
@echo off
set "arr=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79"
set /a min=102, max=105
:main
setlocal enableDelayedExpansion
%const% set MAXNUM=20
for %%a in (%arr%) do set /a num+=1 & set a[!num!]=%%a
if %num% gtr %MAXNUM% echo Are you kidding 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!
    )
)
rem 为枚举组合数生成for嵌套语句
set letters=[abcdefghijklmnopqrstuvwxyz]
for /l %%a in (1 1 %MAXNUM%) do (
    set var=!letters:~%%a,1!
    if 1==%%a (
        set "set_start=set /a start=00+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,^!num^!) do "
    set "exp=!exp!,^!a[%%!var!]^!"
)
rem echo !do!
rem echo !exp!
rem pause
for /l %%a in (1 1 %num%) do (
    set /a minsum=0, maxsum=0
    for /l %%i in (1 1 %%a) do set /a minsum+=a[%%i], n=num-%%i+1&set /a maxsum+=a[!n!]
    rem echo %%a:[!minsum!,!maxsum!]
    if !minsum! leq %max% if !maxsum! geq %min% (
        set /a do_len=54*%%a, exp_len=8*%%a
        call:enum
    )
)
pause
endlocal&exit/b
:enum
setlocal enableDelayedExpansion
set do=!do:~0,%do_len%!
set exp=!exp:~0,%exp_len%!
%do% (
    set /a sum=0%exp:,=+%
    if !sum! geq %min% if !sum! leq %max% echo%exp:,=+%=!sum!
)
endlocal
goto :eofCOPY

TOP

思路比较普通:先排序,分别从数组中取N个数(1≤N≤num)进行组合(先简单判断是否需要取组合数),再将组合数的和与目标比较。取组合数用的是for嵌套循环(利用bat预处理机制),echo !do!就知道展开后是什么了。

之前形成思维定势,老想着因为数组经过排序,所以如果前一组组合数的和大于max,后面就不用比较了,也即下面的当prior(sum)小于max时才比较:
    set /a prior=sum, sum=0
    if !prior! leq %max% (
        for %%a in (%exp%) do set /a sum+=%%a
        if !sum! geq %min% if !sum! leq %max% echo%exp:,=+%=!sum!
    )
还有逻辑问题,完全是废代码。

TOP

递归里面用循环,循环体里面又递归调用,这个递归是很多层的。(这种方法很少用,要死很多脑细胞的)
楼上估计是把递归函数第一个语句还要循环给忘了:
for /l %%i in (%i% 1 %N%) do (

TOP

“调用函数会得到12,123,1234,12345,123456,1234567,12345678。此时跳出函数”
递归函数也有for啊,这个for取第一个值时,通过递归,就得到了12,123,1234,12345,123456,1234567,12345678,还远远没到跳出的时候。每次递归都要带来一次循环,每个循环体里面又要递归……

TOP

返回列表