求对一个简单算法的改进!(20分)

  • 主题发起人 Flashcqxg
  • 开始时间
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
算法很简单:从一个数组中取出N个数,使之和等于一个指定的数。
我是参考的递归算法,但感觉太慢了,不知道有没有好的改进办法,使之更快,请大家多多指教
我的算法如下:
//参数说明:S这指定和
// N为指定取多少个数
// w[]为这些数的数组
function knap(s, n: Integer): Boolean;
begin
if s <= 0 then
knap := True
else
if (s < 0) or ((s > 0) and (n < 1)) then
knap := False
else
begin
if knap(s - w[n], n - 1) = True then
begin

ShowMessage('n为:' + IntToStr(n) + 'w[n]为' + IntToStr(w[n]));
knap := True;
end
else
knap := knap(s, n - 1);
end;
end;
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
补充说明下:
1.对于w[]数组,我已经按其值从大到小排序了的;
2.w[]数组的最大的值<=S
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
这个算法确实不难,但是要高效就很难了,真的很难
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
排序了的数据能简单些,但是也很难
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
请版主LeeChange和张剑波进来看看吧
有没有办法让我的这个需求有个高效的算法。
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
可以参考一下这个帖子:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=555596
该贴题目的要求比楼主的问题更加复杂,可以适当删减:)
 
H

hs-kill

Unregistered / Unconfirmed
GUEST, unregistred user!
排过序那就用二分法查找数据
先取最小的然后从最大的循环判断是否符合,直到找到符合或者小于符合条件数字的项为止,记下这个项为极限项
然后取第2个最小的,从上次取得的项开始,如果上次的项是符合条件就+1,否则就从该项判断
这样循环直到最大的都不能相加符合要求为止
不过这样只适合2个数相加,要是3个数就无能为力了,变数太多,有点类似计算2点间公交换乘
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢:hs-kill。
TO:creation-zy:
我看了你在那个帖子上的程序代码,也实际运行了,速度确实快,感觉不出程序有运行的过程结果就出来了。
不过,我看您的代码眼睛都看花了,也不是看得很明白;
另外,你的代码要求是按升序排序的哈,我的已经按降序排序了。
能不能请你再显身手,结合我的算法重新写一个呢?我可以另外开贴感谢你。
我的要求是:
1、从一个数组W[]中取出指定的N个数,使这N个数的和等于一个指定的数S,并打印出这N个数及位置;
2、要求W[]数组中的每个数只能用一次,因此,使用过了的数,从这个数组中删除。
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
自己顶下。
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
在第二个要求中,提到了“用一次即删除”——难道要给出多个不同的解么?
例如: W=[7,6,5,4,3,2,1,0], N=3, S=12 Result:[7,5,0] [6,4,2]
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
啊!creation-zy终于来了哈。非常感激!
在第二个要求中,提到了“用一次即删除”——难道要给出多个不同的解么?
例如: W=[7,6,5,4,3,2,1,0], N=3, S=12 Result:[7,5,0] [6,4,2]
不是,只需要给出第一个解决就行了。
“用一次即删除”意思是:因为我还要在一个循环中使用这个算法,需要传递不同的N和S的参数进来。而在求解不同的N和S的时候,不能重复使用W[]数组中已经用过的数据了。所以要删除。
 
X

xingxin00

Unregistered / Unconfirmed
GUEST, unregistred user!
应该不难,但高效就不一定了,在线等高手吧。要是数据不是太大用穷举也可以
 
W

wql

Unregistered / Unconfirmed
GUEST, unregistred user!
题外话:
hs-kill很热情!不错!
 
S

SS2000

Unregistered / Unconfirmed
GUEST, unregistred user!
这个算法如果要高效,肯定不是简单算法,一定是要动态规划,再加一些分治算法等等,估计能高效,呵呵。就像排序,是很简单的,但是却有那么多人研究了那么多算法,能说排序是很简单吗?简单,但是高效难!
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢大家的热情帮助
期待中。。。。。
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
请creation-zy再帮忙看看呀,谢谢了。
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
自已顶下。
期待creation-zy 的到来.....
 
N

nicai_wgl

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,想想就头晕,还是数学没学好
 
C

creation-zy

Unregistered / Unconfirmed
GUEST, unregistred user!
将原贴算法中的 for i:=2 to AimNumberdo
改成 for i:=N to Ndo
(N是你给的个数)
就可以了。至于大小排列顺序,自己用循环反序一下啊。
 
F

Flashcqxg

Unregistered / Unconfirmed
GUEST, unregistred user!
creation-zy:
谢谢,我先看看吧。看不懂再说。
您贴的那代码有点复杂,呵呵。
 
顶部