[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
本帖最后由 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个数字的所有组合的话就不知要等到猴年马月了!
  1. @echo off&setlocal enabledelayedexpansion
  2. set str=8, 13, 2,  37, 19, 11, 7,  22, 38
  3. set _51=ok
  4. for %%a in (%str%) do (
  5.     for /f "delims=_=" %%b in ('set _') do (
  6.         set/a sum=%%b+%%a
  7.         if !sum! gtr 102 if !sum! lss 105 echo %%b+%%a=!sum!
  8.         if !sum! lss 104 set _%%b+%%a=ok
  9.     )
  10. set _%%a=ok
  11. )
  12. rem 将后5个数字分别与前面所有组合相组合,并求和判断
  13. for %%a in (52, 61,62, 79, 85) do (
  14.     for /f "delims=_=" %%b in ('set _') do (
  15.         set/a sum=%%b+%%a
  16.         if !sum! gtr 102 if !sum! lss 105 echo %%b+%%a=!sum!
  17. ))
  18. pause
复制代码

TOP

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

TOP

楼上也说说思路吧,直接看代码头晕

TOP

本帖最后由 wankoilz 于 2011-5-8 19:49 编辑

是有点复杂,没怎么看懂,不过楼上用的变量嵌套值得学习!
我求组合的思路是:
先随便拿一个元素出来,比如a,它形成的组合就一个a
然后加入b,它与前面所有已有的组合相组合,这里得到ab。加上前面已有的组合a、自身b,所以a和b形成的组合是a,ab,b
接着加入c,和前面一样,先得到ac,abc,bc,加上已有的和自身c,所有组合就是a,ab,b,ac,abc,bc,c
接下来是d
.
.
.

TOP

ters这种方法会漏掉不少组合吧。
假设有1-15这15个数,在取两个数的组合中就只能得到1-2,2-3,3-4,4-5...14-15,而其它的1-3,1-4,1-5...等都漏掉了

TOP

本帖最后由 wankoilz 于 2011-5-13 22:54 编辑

抱歉,之前不能上网,自己照着手机在电脑上测试了一下你的代码有点问题,现在直接复制代码测试是没问题的。
看来我还没高清楼上的算法,请教下:楼上代码的运行结果中,从 12,123,1234,12345,123456,1234567,12345678后接着是123456 8 ,为什么会有123456 8这个结果呢(按照我的理解接下来应该是23,234,2345,23456...),不懂...

TOP

本帖最后由 wankoilz 于 2011-5-15 19:48 编辑

我的理解是:批处理开始执行第一个for,调用函数会得到12,123,1234,12345,123456,1234567,12345678。此时跳出函数,回到for,再调用函数得到23,234,2345,23456,234567,2345678
我就想知道我在18楼说的123456 8的结果是怎么来的(代码具体是如何执行的),恕我愚钝哪...

TOP

本帖最后由 wankoilz 于 2011-5-18 14:30 编辑

感谢powerbat讲解。确实!我之前还以为批处理递归没有这种“堆栈”的效果,结果测试了一下还真如楼上所说:每次call 都带来一次循环,那些被call阻挡的,没来得及执行的代码似乎被放入类似“堆栈”的结构里,在call完毕之后都陆续被执行了。测试如下:
  1. @echo off&setlocal enabledelayedexpansion
  2. call :lp
  3. pause
  4. :lp
  5. for /l %%a in (1,1,5) do (
  6.     echo %%a
  7.     set/an+=1&if !n! equ 3 call :lp
  8. )
复制代码
第一次for:本该执行5次echo%%a,但执行到3的时候被call :lp阻断了(此时echo 4和echo 5被“存”起来了),接着就完整的执行了一次for,完了把存起来的echo 4和echo 5也执行了,所以有如下结果(用空行分隔了一下,方便分析):
  1. 1
  2. 2
  3. 3
  4. 1
  5. 2
  6. 3
  7. 4
  8. 5
  9. 4
  10. 5
复制代码
而且这种存储确实是按照类似“堆栈”的方式,即“后进先出”,从下面代码,的执行结果就可以看出来:
  1. @echo off&setlocal enabledelayedexpansion
  2. call :lp
  3. pause
  4. :lp
  5. for /l %%a in (1,1,5) do (
  6.     echo %%a
  7.     set/an+=1
  8.     if !n! equ 3 call :lp
  9.     if !n! equ 5 call :lp
  10. )
复制代码
结果(用空行分隔了一下,方便分析):
  1. 1
  2. 2
  3. 3
  4. 1
  5. 2
  6. 1
  7. 2
  8. 3
  9. 4
  10. 5
  11. 3
  12. 4
  13. 5
  14. 4
  15. 5
复制代码
第一个for,执行到3的时候被call阻断,输出1,2,3(echo 4和echo 5被保存),然后执行第二次for,执行到2的时候n等于5了,再次call,这时输出1,2(echo 3,echo 4,echo 5被保存),然后是最后一个完整的for,输出1,2,3,4,5。完了执行被保存的call(后保存的先执行),输出3,4,5和4,5。
这样看来15楼的代码是很不错的!

TOP

返回列表