我必須找到滿足某些規則的20個元素的所有可能的排列組合。例如,元素1不能位於位置3,4,6,7,8,12和17,元素2不能位於位置1,2,7,10,19等等。目前,我正在使用遞歸函數來檢查所有可能的排列,並檢查規則是否滿足。這對10個元素(10個排列組合)來說效果很好,但是你可以想象這個算法不再可用於20個元素。有誰知道更有效的方法,可以跳過不需要的排列? (我假設,從20 = 2.4E18可能的排列只有1-2 Mio.將滿足規則20個元素的排列,滿足一定的規則
這是我在用的,現在(Pascal代碼中)!
procedure permu(p:feldtyp; ka:bereich);
var
i,h : bereich;
label skip;
begin
if ka=teams then begin
//execute certain tests, skip the output part if the tests fail
for i:=1 to ka do if ((hh11[P[i]]+hh21[i])<>(ka-1)) or
((patterns[h1[P[i]]][teams-1]=patterns[h2[i]][1]) and ((patterns[h1[P[i]]][teams-1]=patterns[h1[P[i]]][1])=(patterns[h2[i]][teams-1]=patterns[h2[i]][1]))) or
((patterns[h1[P[i]]][teams-1]<>patterns[h2[i]][1]) and ((patterns[h1[P[i]]][teams-1]=patterns[h1[P[i]]][1])<>(patterns[h2[i]][teams-1]=patterns[h2[i]][1]))) or
((patterns[h1[P[i]]][teams-1]<>patterns[h2[i]][1]) and ((patterns[h1[P[i]]][teams-1]=patterns[h1[P[i]]][1]) and (patterns[h2[i]][teams-1]=patterns[h2[i]][1]))) or
((patterns[h1[P[i]]][teams-1]=patterns[h2[i]][1]) and ((patterns[h1[P[i]]][teams-2]=patterns[h1[P[i]]][teams-3]) or (patterns[h2[i]][2]=patterns[h2[i]][3]))) or
((patterns[h1[P[i]]][teams-1]=patterns[h1[P[i]]][teams-2]) and (patterns[h2[i]][1]=patterns[h2[i]][2]))
then goto skip;
//all tests passed, write permutation
// ...
skip:
end
else begin
for i := ka to teams do begin
h := P[i];
P[i] := p[ka];
P[ka] := h;
permu(p, ka+1);
end;
end;
end;
( 「groups」是常量20和「h1」,「h2」是其他地方定義的一些數組[1..20]。此外定義了一個用於派生規則的全局二維數組「模式」。被看作是具有n行和19列的大0-1矩陣)
像這樣proably:獲取每個元素的所有允許位置的列表,使用遞歸函數將每個元素放置在每個空閒的允許位置,然後遞歸地繼續下一個元素 – BeniBela