找回密码
 加入
搜索
楼主: afan

[效率算法] 从一组数字中任意组合N个数字,使之和在某个数值范围

 火... [复制链接]
发表于 2010-1-24 09:03:13 | 显示全部楼层
看看~~~~~~~~~~~~~~
发表于 2010-1-24 09:30:46 | 显示全部楼层
对于数学类的实在...
发表于 2010-1-24 10:28:58 | 显示全部楼层
我也来试一下,看看速度如何
发表于 2010-1-24 10:35:42 | 显示全部楼层
先看看源码先吧
发表于 2010-1-24 13:27:38 | 显示全部楼层
本帖最后由 supersp 于 2010-1-24 14:27 编辑

回复 43# afan

要跳出递归,其实很简单...
加个变量判断就行, 在程序中的2个地方使用了FOR,而递归的时候实际上每一层都有FOR循环的, 找到合适的值后,exitloop 1 就能让程序一层一层跳出来,延迟是有..但也就几个毫秒的事。
而且递归的时候直接跳到主程序可能引发内存问题..
那段代码我测试了很多组合,平均每找到一个组合耗时 0.8 ms..
下面这段39个元素,编译器里跑,4-5ms,还有可能2ms耗在数组排序上
#Include <Array.au3>


Dim $aArray[39] = [28,15,34,48,51, 8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79, 53,54,55,56,57,58,59,60,63,64,90,91,92,93,94,95,96,97,98,99]
$begin = TimerInit()
_ArraySort($aArray)
$m = UBound($aArray)
Global $display[1]
Global $jump=0 ;递归退出变量
;折半法,找出 105/2 的分界线
Local $min=0,$max=$m-1,$mid,$fjx=-1
If $aArray[0]>=58 Then $fjx=0
If $aArray[$max]<58 Then $fjx=$max
While $fjx=-1
        $mid=($min+$max)/2
        If $aArray[$mid] >= 58 Then 
                $max=$mid-1
                If $aArray[$mid-1] < 58 Then $fjx=$mid
        Else
                $min=$mid+1
                If $aArray[$mid+1] >= 58 Then $fjx=$mid+1
        EndIf
WEnd

_xh(0,"",$fjx-1)
For $v2 = $fjx To $m-1
        If $jump Then ExitLoop
        _xh($aArray[$v2],String($aArray[$v2])&"+",$fjx-1)
Next
_ArrayDelete($display, 0)
$dif = TimerDiff($begin)
_ArrayDisplay($display,"耗时:"&$dif)


Func _xh($var,$str,$n)
        For $i = $n To 0 Step -1
        If $jump Then ExitLoop
                $num = Execute("$var + $aArray[$i]")
                Switch $num
                        Case 103 To 104
                                _ArrayAdd($display,$str&String($aArray[$i])&"="&String($num))
                      $jump=1
                      ExitLoop
                        Case 1 To 102
                                _xh($num,$str&String($aArray[$i]&"+"),$i-1)
                        Case Else
                                ContinueLoop
                EndSwitch
        Next
EndFunc

评分

参与人数 1金钱 +80 贡献 +5 收起 理由
afan + 80 + 5 学习了

查看全部评分

 楼主| 发表于 2010-1-24 15:23:53 | 显示全部楼层
回复 50# supersp


    感谢指点~
发表于 2010-1-24 16:33:31 | 显示全部楼层
学习下先,想不出来 
发表于 2010-1-24 18:50:07 | 显示全部楼层
回复 36# supersp
这个算法非常的牛
发表于 2010-1-25 17:06:52 | 显示全部楼层
本帖最后由 sanmoking 于 2010-1-25 18:54 编辑

重新加上注释:
Dim $aArray[14] = [8, 13, 2, 52, 61, 37, 85, 19, 11, 7, 62, 22, 38, 79]
$p = "";存储结果
$coo = 0 ;存储计算次数
$num = UBound($aArray) - 1 ;计算数组最后一位
$begin = TimerInit();开始计时
mimi(0, 0, "")
$dif = TimerDiff($begin);结束记时

GUICreate("", 400, 320)
GUICtrlCreateList("", 10, 10, 380, 300)
GUICtrlSetData(-1, "计算耗时: " & $dif)
GUICtrlSetData(-1, "计算" & $coo & "次加法运算得到符合的结果:" & $p)
GUISetState()
While GUIGetMsg() + 3
WEnd
Func mimi($k, $resd, $txtd)
 If $p = "" Then;如果结果为空
  For $i = $k To $num
   $resx = $resd + $aArray[$i]
   $txtx = $txtd & $aArray[$i] & "+"
   $coo += 1;统计加法运算次数
   If $resx <= 102 Then
    mimi($i + 1, $resx, $txtx)
   ElseIf $resx > 102 And $resx < 105 Then
    $p = StringReplace($txtx & "=", "+=", "=") & $resx;得到结果
    ExitLoop
   EndIf
  Next
 EndIf
EndFunc   ;==>mimi

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +80 贡献 +5 收起 理由
afan + 80 + 5 学习了

查看全部评分

发表于 2010-1-25 17:38:32 | 显示全部楼层
之前12楼的那个代码错了,见【这个帖子
发表于 2010-1-26 11:19:16 | 显示全部楼层
看看。学习一下啊
发表于 2010-1-26 15:27:01 | 显示全部楼层
回复看看,,没看懂题目意思
发表于 2010-1-26 20:36:05 | 显示全部楼层
这个没什么意思,楼主真无聊
 楼主| 发表于 2010-1-26 20:59:54 | 显示全部楼层
这个没什么意思,楼主真无聊
xiong616 发表于 2010-1-26 20:36



    这是有没有意思的问题吗? 为什么无聊?

回答不上or不回答直接禁言。
发表于 2010-1-26 21:13:22 | 显示全部楼层
本帖最后由 xiong616 于 2010-1-26 21:25 编辑

回复 59# afan


    这个是算法的问题,而且是最简单的一种。学习任何一种语言的时候,这种问题会放在最前面进行讲解,不信你可以去翻翻任何一本语言类书籍。C,C++,Java,C#等等。。。
快速排序的方法也就那么几种,排序后再进行筛选。算法的效率也就取决于排序的时间和筛选的时间。本人QA不是RD但这个还是懂的,麻烦楼主没事的时候可以多看看语法书。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-25 09:15 , Processed in 0.073520 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表