[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

批处理从一组数字中取任意个数字之和在一个数值范围内

假如有这么一组数字
{51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79}
使其中N个数字的和sum满足  102<sum<105
并打印出来。
好吧,好像难度过高,那么改为可以支持<=40个数字的组合,每个数字<100。

结果如下:

算了,我自己放一组代码吧。
  1. @ECHO OFF&SETLOCAL ENABLEDELAYEDEXPANSION
  2. set "sz=51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79"
  3. for %%i in (!sz!) do (
  4.       set "array=_%%i_ !array!"
  5.       for %%j in (!array!) do (
  6.           for /f "delims=_" %%k in ("%%j") do (
  7.               if %%i gtr %%k (
  8.                   set "array=!array:_%%i_=#!"
  9.                   set "array=!array:_%%k_=_%%i_!"
  10.                   set "array=!array:#=_%%k_!"
  11.               )
  12.            )
  13.       )
  14. )
  15. set "array=!array:_=!"&for %%i in (!array!) do (
  16.       if %%i lss 58 (
  17.           set /a n+=1
  18.           set "min_!n!=%%i"
  19.       ) else (
  20.           set "_max=!_max! %%i"
  21.       )
  22. )
  23. for %%i in (0 !_max!) do (
  24.     call :loop %%i !n!
  25. )
  26. goto :eof
  27. :loop [next] [cut]
  28. for /l %%n in (%2,-1,1) do (
  29.     set str=%1+!min_%%n!
  30.     if %1 equ 0 set str=!min_%%n!
  31.     set /a v=!str!
  32.     if !v! lss 105 if !v! gtr 102 echo,!str!=!v!
  33.     if !v! lss 103 (
  34.             set /a cut=%%n-1
  35.             call :loop !str! !cut!
  36.      )
  37. )
复制代码

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

好吧,其实我忘了说。。
每个数字只用一次来的。。

TOP

本帖最后由 caruko 于 2011-5-8 23:14 编辑

其实有想过只用一层循环来解决,通过一些判断来控制参与计算的变量就可以了。
但循环次数需要先计算全排列次数出来,可是全排列的数字超过13个就溢出了。
没有while条件的循环,用goto实际上跟call差不多效率。

TOP

返回列表