Office中国论坛/Access中国论坛

标题: 趣味找数字 [打印本页]

作者: tanhong    时间: 2008-6-4 20:56
标题: 趣味找数字
一张表中的几百个数字中查找出并提示出三个数,且这三个数之和等于768.68

这是一个网友的求助,觉得挺有意思的,希望各位高手开动一下思路,出手相助之.
作者: pureshadow    时间: 2008-6-4 22:28
笨妖想很久了.........[:30]
作者: chenwm1973    时间: 2008-6-5 08:14
我觉得只能用枚举法,如果数据不再增加,那还能忍受,否则.......
[:31] [:31] [:31]
作者: tanhong    时间: 2008-6-5 08:37
原帖由 chenwm1973 于 2008-6-5 08:14 发表
我觉得只能用枚举法,如果数据不再增加,那还能忍受,否则.......
[:31] [:31] [:31]


如果用枚举法,那运算的量将非常庞大,有没有更好的算法
作者: rjacky    时间: 2008-6-5 08:54
为什么之和要是768.68[:45]
作者: tanhong    时间: 2008-6-5 09:01
原帖由 rjacky 于 2008-6-5 08:54 发表
为什么之和要是768.68[:45]


是网友的要求,你也可以用其它的数
作者: ui    时间: 2008-6-5 09:09
只能逐个去对比了, 可能算法会影响速度
作者: caojun19730918    时间: 2008-6-6 21:01
[:50]
作者: 欢欢    时间: 2008-6-9 14:06
标题: 这样可以吗?数值区域在A6:O50
Sub quweishuzi()
For X1 = 1 To 15
   For Y1 = 6 To 50
    a = Cells(Y1, X1)
      For X2 = 1 To 15
         For Y2 = 6 To 50
           b = Cells(Y2, X2)
            For X3 = 1 To 15
              For Y3 = 6 To 50
                c = Cells(Y3, X3)
                 If a + b + c = 254 Then
                    MsgBox "第一个数" & a & "地址在" & Chr(64 + X1) & Y1 & Chr(13) _
                         & "第二个数" & b & "地址在" & Chr(64 + X2) & Y2 & Chr(13) _
                         & "第三个数" & c & "地址在" & Chr(64 + X3) & Y3 & Chr(13)
                         Exit Sub
                  End If
                 Next
              Next
            Next
         Next
     Next
   Next
End Sub
作者: tanhong    时间: 2008-6-9 23:51
原帖由 欢欢 于 2008-6-9 14:06 发表
Sub quweishuzi()
For X1 = 1 To 15
   For Y1 = 6 To 50
    a = Cells(Y1, X1)
      For X2 = 1 To 15
         For Y2 = 6 To 50
           b = Cells(Y2, X2)
            For X3 = 1 To 15
         ...


总算看到有人打擂了,哈哈!  [:50]
作者: lishengjun    时间: 2008-6-30 11:38
老谭能否给发出一个原表,让大家可以根据原表然后在上面做题。然后把答案附上来不是更好吗。

[ 本帖最后由 lishengjun 于 2008-6-30 11:41 编辑 ]
作者: tanhong    时间: 2008-6-30 11:49
原帖由 lishengjun 于 2008-6-30 11:38 发表
老谭能否给发出一个原表,让大家可以根据原表然后在上面做题。然后把答案附上来不是更好吗。


哈哈!你怎么知道我真实姓名?[:33]
作者: pureshadow    时间: 2008-6-30 17:03
你的真名,地球人都知道了
作者: tanhong    时间: 2008-7-1 09:49
原帖由 pureshadow 于 2008-6-30 17:03 发表
你的真名,地球人都知道了
[:30] [:31]
作者: lishengjun    时间: 2008-7-2 17:58
老谭不是我们本事大,只能怪你的名声响。[:13]
作者: dsj625    时间: 2009-1-17 13:09
谁能搞出个实例来,我也想用
作者: 极冰    时间: 2009-1-31 15:04
到底是怎么样的一张数字表格,想了解详细一点。。
作者: _ss_bri    时间: 2009-2-1 20:04
用EXCEL 的规划求解
作者: ACMAIN_CHM    时间: 2009-2-1 20:43
3个数字的话,如果这几百个数字小 256,则可以直接用EXCEL操作来实现。

第一行,从B1 - IV1为这个序列。
第一行,从A2 - A256相同,转置一下就成了。

然后公式就简单了。 B2=  B$1+$A2
在300行,复制一遍第一行,B301 = B$300+B2,向下复制公式,之后,用条件格式标出=768.68的单元格。

在公式中可以对column(),row()进行判断,已确保同一数字不被选择两次。



******************
*  一切皆有可能  *
******************


QQ群 48866293 / 12035577 / 7440532 / 13666209
作者: ACMAIN_CHM    时间: 2009-2-1 21:00
方法二,
直接在EXCEL中利用 MS Query进行SQL语句的查询
假设sheet1中放两列, FD01列为序号,也确保不重复挑选同一数字。 FD02为这些数字
AB C
1FD01FD02
2115.6
3277.2

然后在QUERY中执行如下语句。(需要耐心,速度比较慢)
SELECT a.FD02,b.fd02,c.fd02
FROM `C:\temp\Book5`.`Sheet1$` as a,
`C:\temp\Book5`.`Sheet1$` as b,
`C:\temp\Book5`.`Sheet1$` as c
where a.fd01<b.fd01
and b.fd01<c.fd01
and a.FD02 + b.fd02 + c.fd02=768.68



******************
*  一切皆有可能  *
******************

QQ群 48866293 / 12035577 / 7440532 / 13666209
作者: ACMAIN_CHM    时间: 2009-2-1 21:29
方法三:用程序来解决.

Option Explicit

Public Sub test()
    Dim fArray() As Single
    Dim nTotalNumberCnt As Integer
    nTotalNumberCnt = Sheet1.UsedRange.Rows.Count


    ReDim fArray(nTotalNumberCnt)

    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
   
    For i = 1 To nTotalNumberCnt
        fArray(i) = Sheet1.Cells(i, 1).Value
    Next i
   
    Dim fSum As Single
   
    fSum = 768.68
   
    Debug.Print "begin ......"
   
    For i = 1 To nTotalNumberCnt - 2
        For j = i + 1 To nTotalNumberCnt - 1
            For k = j + 1 To nTotalNumberCnt
                If fArray(i) + fArray(j) + fArray(k) = fSum Then
                    Debug.Print i; fArray(i), j; fArray(j), k; fArray(k)
                End If
            Next k
        Next j
    Next i
   
    Debug.Print "end ......"
End Sub




******************
*  一切皆有可能  *
******************

QQ群 48866293 / 12035577 / 7440532 / 13666209
作者: ljw990485    时间: 2009-2-23 20:41
本帖最后由 ljw990485 于 2009-2-23 21:01 编辑

找3个数就好办,穷举也很快,
option base 1
dim i as integer,j as integer,k as integer,A() as double,Target as double
dim t as double
n=?多少个就输入多少吧
Redim A(n),自己写程序输入这n个数和目标数Target
for i=1 to n-2
    for j=i+1 to n-1
        t=A(i)+A(j)
        for k=j+1 to n
           if abs(t+A(k)-Target)<1.0e-10 then
               输出 i,j,k,只找一组的话就结束
        endif
  多个next
以上程序循环次数
1)给定i,j
k循环 n-(j+1)+1=n-j次
2)故给定i后,j,k循环次数为
[n-(i+1)]+[n-(i+2)]+...+1=(n-i)(n-i-1)/2=(n-i)^2/2-(n-i)/2
3)最大循环次数
[(n-1)^2+...+2^2]/2-[(n-1)+...+2]/2
=n(n-1)(n-2)/6=O(n^3/6)
n=1000时,最大循环数为166167000,不算大,关键是运算非常简单
作者: ljw990485    时间: 2009-2-23 20:43
如果用0-1规划的方法,也可以,但可能会带来误差的问题
而穷举的方法只有2个加法,舍入误差的影响比较小
作者: ljw990485    时间: 2009-2-23 21:09
本帖最后由 ljw990485 于 2009-2-25 00:04 编辑

靠,程序一样的

不过有一个地方不一样,大家看出来了吗?

fArray(i) + fArray(j) + fArray(k) = fSum

1)浮点数不能这样判断是否相等
2)多一次加法,循环很多次的话,量就很大哦
作者: 一朵白云    时间: 2010-4-27 22:04
我想不出来
作者: li-lin3000    时间: 2011-1-14 07:59
速度是问题
作者: 伊斯特伍德    时间: 2013-4-20 13:55
本帖最后由 伊斯特伍德 于 2013-4-20 14:05 编辑

必须用枚举法吧。
看了前面几位同学的解法,感觉算法上应该还可以再优化一下,就是:
如果把这N个数排序,然后从小到大(或者从大到小)先确定两个数字,比如:K1(代表A1),K2(代表A2)(表示最小的两个),剩下的A3至An,采用二分法查找,如果没有查到,K1K2再递增(内层是K2,外层是K1,且K2的起点是K1的后续单元格,且K2<(S-K1)/2),直到K1>=S/3
这样子算法,在超级大数据里的情况下(比如10000数据里要查找3个符合条件的记录),可以省掉很多的枚举量.



PS:VBA还是不熟悉,就不写VBA代码出来让大家见笑了.

作者: 伊斯特伍德    时间: 2013-4-20 14:11
判断是否相等涉及到精度的问题,这个不管用什么算法应该都是会遇上的.
只能是改成判断三个数相加和S值的接近程度,比如:误差小于0.000 000 01,这就要求被查的一组数据精度有一定的限制




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3