特定のルールを満たす20個の要素のすべての可能な順列を見つける必要があります。たとえば、要素1を位置3,4、6、7、8、12、および17に配置することはできません。要素2を位置1、2、7、10、19に配置することはできません。現在、私はすべての可能な順列を通過し、ルールが満たされているかどうかをチェックする再帰関数を使用しています。これは10個の要素(10!順列)で完全に正常に機能しますが、ご想像のとおり、アルゴリズムは20個の要素では使用できなくなります。不要な順列をスキップするより効率的なアプローチを知っている人はいますか?(20!= 2.4E18の可能な順列から、1〜2Mioのみがルールを満たすと思います。
これは私が今使っているものです(パスカルコード):
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;
(「teams」は定数20、「h1」、「h2」は別の場所で定義されたいくつかの配列[1..20]です。さらに、ルールを導出するために使用されるグローバル2次元配列「patterns」が定義されています。この配列n行19列の大きな0-1行列として見ることができます)