遍历所有组合的写法???难道只有一种写法吗???????????????? (100分)

  • 主题发起人 主题发起人 ReallyFail
  • 开始时间 开始时间
R

ReallyFail

Unregistered / Unconfirmed
GUEST, unregistred user!
比如是c 7 4,就是从7个中选四个的所有组合情况??
前几天用了很野蛮的做法就是定义四重的循环,并在循环中判断
当前层的循环变量是否与上一层的循环变量相同,如果相同的话就BREAK掉!
各位有没更好的办法了???因为假设我要的是100选3的组合,那我不是要
写一个100重的循环了???急啊!!!各位帮帮忙!!!!!!!!!!
 
用递归最简单
 
楼上的,说的更细点????
 
用集合啊!
 
两位老兄的嘴巴怎么都象皇帝的金口一样难开啊??
 
给你个更精练的回答:回溯法.
 
UP
讲清楚D
 
小弟我在算法方面都是要用的时候再去翻书的。这几天书被人给拿了,所以就跑上来问了。就如
LeeChange老兄说的用回朔,我有比较深的印象,在程序员考试教材上有个例子跟我的问题很
类似,但书没了,只好让大家解释得稍微清楚一点了!!
 
只要递归就可以了,因为是穷尽,没有约束条件,不需要回溯。
思想是:
从N个数a1,a2,...a(n)中选M个可以分解为:
1.选取a(n),并从a1,a2,...a(n-1)选M-1个
2.从a1,a2,...a(n-1)中选M个。
这样规模可以不断减少,
假如递减到N=M时,直接全选择,并打印结果。
如果M=0那么直接打印结果。
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=0938125
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1135640
自己看吧。

鉴于大多数人通常不理会链接...贴!
//TBuffer类的代码见 http://www.delphibbs.com/delphibbs/dispq.asp?lid=0968511
function CNMNum(N,M:Integer):Double;
var
i:Integer;
begin
Result:=1;
for i:=N-M+1 to Ndo
Result:=Result*i;
for i:=2 to Mdo
Result:=Result/i;
end;
function CNM(const N,M:Integer;out Count:Integer):String;
var
A,R:array of Integer;
i:Integer;
Buf:TBuffer;
StartTime:DWord;
TotalCount:Double;
procedure Gen(Level:Integer);
var
j,s:Integer;
mstr:String;
begin
if Level=M then
begin
mstr:='';
for j:=0 to M-1do
mstr:=mstr+IntToStr(R[j])+#9;
mstr:=mstr+#13#10;
Buf.WriteBuf(@mstr[1],Length(mstr));
Inc(Count);
if Count mod 1000=0 then
begin
Form1.Caption:=Format('%.3f%% %.7d Time: %.2fs Buffer Size: %.2fM',
[100*Count/TotalCount,Count,(GetTickCount-StartTime)/1000,
Buf.ContentSize/(1024*1024)]);
Application.ProcessMessages;
end;
exit;
end;
if Level=0 then
s:=0
else
s:=R[Level-1]+1;
for j:=s to N-M+Leveldo
begin
R[Level]:=j;
Gen(Level+1);
end;
end;
begin
Result:='';
Count:=0;
if (N<1) or (M>N) or (M<1) then
exit;
Buf:=TBuffer.Create(0,1024*1024);
SetLength(A,N);
SetLength(R,M);
TotalCount:=CNMNum(N,M);
StartTime:=GetTickCount;
for i:=0 to N-1do
A:=i;
Gen(0);
Result:=Buf.AsString;
Buf.Free;
end;
 
谢谢各位大虾!!
 
后退
顶部