미로 문제에 대한 비 수소 솔루션?
-
22-08-2019 - |
문제
각 노드가 최대 3 명의 자녀와 3 명의 부모가있는*n 크기의 멀티 헤드 acyclic 그래프가 주어지면, 두 노드가 동일한 값을 공유하지 않는 곳에 n 길이 경로가 존재하는지 여부를 식별하기위한 비 수소 알고리즘이 있습니까? 세트의 가치가 설명되어 있습니까?
기본적으로, 나는 각 공간에 임의의 값 (1..n)이있는 n*n 미로가 있습니다. 모든 값을 포함하는 N 노드의 경로 (상단에서 하단까지)를 찾아야합니다.
지금은 깊이 우선 검색을 사용하고 있지만 T(n) = 3T(n-1) + O(1)
, 그것은 O(3^n)
, 비 이상적인 솔루션.
내 두려움을 확인하거나 올바른 방향으로 나를 가리키는 것은 대단히 감사 할 것입니다.
편집 : 이것을 조금 더 구체적으로 만들려면 여기에 솔루션이있는 미로 (깊이 우선 솔루션을 사용하여 해결)가 있습니다.
1 2 5 5 4 1 5 1 3 5 4 1 2 3 2 5 5 4 4 3 4 2 1 2 4 S3, 5, 1, 3, 4, 2, F4 S3, 5, 1, 3, 4, 2, F2 S3, 5, 1, 3, 4, 2, F4 S3, 5, 3, 2, 4, 1, F3 S3, 5, 3, 2, 4, 1, F3 S3, 5, 3, 2, 4, 1, F3 S4, 5, 3, 2, 4, 1, F3 S4, 5, 3, 2, 4, 1, F3 S4, 5, 3, 2, 4, 1, F3 S4, 5, 1, 3, 4, 2, F4 S4, 5, 1, 3, 4, 2, F2 S4, 5, 1, 3, 4, 2, F4 S5, 4, 3, 2, 5, 1, F3 13 total paths`
해결책
이 문제는 NP- 완성이므로 다항식 시간 솔루션이 있는지 여부는 알려져 있지 않습니다. (실제로는 쉽게 쉬울 수있는 표준의 프로비시서입니다. 등., 모두 적용됩니다.) 가능한 감소는 3SAT입니다.
(a ∨ b ∨ c) ∧ (¬a ∨ ¬b ∨ ¬c)와 같은 3SAT 인스턴스가 있다고 가정합니다. "가제트"를 사용하여 문제의 인스턴스를 구축하는 방법을 보여 드리겠습니다. 시작하기 전에 3SAT 문제를 A1 = A2, B1 = B2 및 C1 = C2와 함께 (a1 ∨ b1 ∨ c1) ∧ (¬A2 ∨ ¬B2 ° ¬c2)로 다시 작성하십시오. 즉, 변수의 각 발생을 독특하게 만들지 만 동일한 변수의 다른 발생이 동일해야한다는 조건을 추가하십시오.
먼저, 첫 번째 행에서 숫자 0을 선택하여 나중에 피해야 할 "센티넬"으로 사용할 수 있도록해야합니다.
0 0 0
이제 A1 = A2 규칙을 시행하는 가제트를 구축합니다. _
다음은이 가제트를 사용할 때마다 새로운 고유 번호가 있습니다)
0 _ 0
a1 0 ¬a1
a2 0 ¬a2
첫 번째 줄로 인해 0을 피해야합니다. 이것은 당신이 "a1, a2"또는 경로 "¬a1, ¬a2"경로를 취한다는 것을 의미합니다. 전자는 (약간 혼란스럽게) 설정에 해당하는 반면, 후자는 A를 true로 설정하는 것에 해당합니다. 이것은 우리의 조항 가제트가 정말 쉽기 때문입니다. 우리는 단순히 절을 적어두기 때문에 (다시. _
다음은 매번 새로운 변수입니다) :
0 _ 0
a1 b1 b2
또는
0 _ 0
¬a1 ¬b1 ¬b2
마지막으로, A1과 A1 등을 사용 했으므로 자유롭게 사용하지 않은 것들을 가져갈 수 있습니다.
0 _ 0
a1 ¬a1 0
A1과 A1 중 하나가 변수 선택 가제트에 사용되었을 수도 있고 다른 하나는 조항에 사용되었을 수 있기 때문에 이것은 작동하지 않습니다. 따라서 새로운 변수가 포함되어 있습니다 @i
변수 중 하나 대신 취할 수있는 각 조항에 대해. 따라서 1 항에 변수 A1이 나타나면
0 _ 0
a1 ¬a1 @1
다음은 원래 3SAT 조항의 번역 (A 및 B를 True To True, C -false, 첫 번째 조항에서 A를 선택하는 경로를 강조하고 오른쪽에는 숫자와 광택이있는 경로의 전체 출력입니다. 가제트는 다시 주문됩니다 (첫 번째 조항 가제트, 각 변수, 평등 기기 및 사용되지 않은 가제트)에 대해) 그러나 어쨌든 독립적이기 때문에 중요하지 않습니다.
0 0 < 0 . . < .
0 8 < 0 . _ < .
2 < 4 6 a1 < b1 c1
0 16 < 0 . _ .
11 13 15 < -a2 -b2 -c2<
0 17 < 0 . _ < .
2 0 3 < a1 . -a1<
10 0 11 < a2 . -a2<
0 18 < 0 . _ < .
2 3 1 < a1 -a1 @1 <
0 19 < 0 . _ .
10 < 11 9 a2 < -a2 @2
0 20 < 0 . _ < .
4 0 5 < b1 . -b1<
12 0 13 < b2 . -b2<
0 21 < 0 . _ < .
4 < 5 1 b1 < -b1 @1
0 22 < 0 . _ < .
12 < 13 9 b2 < -b2 @2
0 23 < 0 . _ < .
6 < 0 7 c1 < . -c1
14 < 0 15 c2 < . -c2
0 24 < 0 . _ < .
6 7 < 1 c1 -c1< @1
0 25 < 0 . _ < .
14 15 9 < c2 -c2 @2 <
(모든 것이 정사각형이되기를 원한다면 각 줄의 끝에 여러 개의 0을 포함시킵니다.) 이것을 어떻게 해결하더라도, 3SAT 문제를 해결하고 있다는 것을 알게되어 재미 있습니다.
내 게시물의 끝에는 양식 입력에서 문제 중 하나를 생성하는 급히 작성된 Perl 프로그램이 있습니다.
a b c
-a -b -c
문제의 결과 인스턴스의 변수 수는 다음과 같습니다. 11C + V + 1
. 프로그램을 제공하십시오 -r
숫자 대신 광택을 생성하도록 전환하십시오.
# Set useful output defaults
$, = "\t"; $\ = "\n";
# Process readability option and force sentinel
my $r = "0";
if( $ARGV[0] =~ /-r/ ) { shift; $r = "."; }
print $r, $r, $r;
# Clause gadgets
my( %v, %c, $m, $c );
$m = 1;
while( <> ) {
my( @v, @m );
$c = $m++;
chomp; @v = split;
for my $v ( @v ) {
push @{$v{strip($v)}}, -1; # hack, argh!
push @m, ($r ? $v.@{$v{strip($v)}} : $m + neg($v));
$c{($r ? (strip($v).@{$v{strip($v)}}) : $m)} = $c;
$v{strip($v)}->[-1] = ($r ? (strip($v).@{$v{strip($v)}}) : $m);
$m += 2 unless $r;
}
print $r, newv(), $r;
print @m;
}
# Variable gadget
for my $v ( sort keys %v ) {
# Force equal
print $r, newv(), $r;
for my $n ( @{$v{$v}} ) {
print $n, $r, ($r ? "-".$n : $n+1);
}
# Unused
for my $n ( @{$v{$v}} ) {
print $r, newv(), $r;
print $n, ($r ? "-".$n : $n+1), ($r ? "\@".$c{$n} : $c{$n});
}
}
# Strip leading -
sub strip {
my( $v ) = @_;
return substr $v, neg($v);
}
# Is this variable negative?
sub neg {
my( $v ) = @_;
return "-" eq substr( $v, 0, 1 );
}
# New, unused variable
sub newv {
return "_" if $r;
return $m++;
}
다른 팁
나는 이것이 다항식 시간에 할 수 있다고 확신합니다. 나는 빈 세트로 시작한 다음 줄을 위로 아래로 루프합니다. 나는 모든 종류의 코드를 건너 뛰고 거기에서 알고리즘을 구성 할 수 있어야하는 각 단계에서 상태가 어떻게 보일지 보여줄 것입니다. 나는 가장 좋은 경우가 폭을 먼저 검색하고 테이블의 현재 좋은 경로를 추적하는 것을 사용하여 O (n^2)보다 약간 더 나쁘다고 확신합니다.
편집하다: 이것이 여전히 빠르지 않으면 적용하여 개선 할 수 있습니다. 할리퀸의 최적화.
예를 들어:
1 2 3
3 2 1
1 2 1
상태 0 : r = 0 // 행 p = {} // 경로 세트
// {{Path so far}, Column}
P' = {
{{1}, 0}
{{2}, 1}
{{3}, 2}
}
P = P'
상태 1 : r = 1 // 행 p = {{{1}, 0} {{2}, 1} {{3}, 2}}
P' = {
{{1 3}, 0}
{{1 2}, 1}
{{2 3}, 0}
{{2 1}, 2}
{{3 2}, 1}
{{3 1}, 2}
}
상태 2 : r = 2 p = {{{1 3}, 0} {{1 2}, 1} {{2 3}, 0} {{2 1}, 2} {{3 2}, 1} { {3 1}, 2}}
P' = {
{{1 3 2}, 1}
{{2 3 1}, 0}
{{3 2 1}, 0}
{{3 2 1}, 2}
{{3 1 2}, 1}
}
결과:
경로 수 : 5
S1 1 3 2 F2
S2 2 3 1 F1
S3 3 2 1 F1
S3 3 2 1 F3
S3 3 1 2 F2
당신은 시도 할 수 있습니다 개미 식민지 최적화. 완벽한 솔루션에 매우 가까운 매우 좋은 결과를 빠르게 산출합니다.
하나의 최적화 Kevin Loney의 솔루션 동일한 열에서 동일한 요소를 포함하는 부분 경로를 병합하는 것일 수 있습니다. 끝에 솔루션 수를 알고 싶다면 경로와 합병 수를 기록해야합니다.
예 : 5x5 예제에서 세 번째 행에 도착하면 세 번째 열에는 세 가지 경로가 있으며 (1 2 5) 순서로 포함됩니다. 이 시점과 별도로 따를 필요는 없지만 합병 할 수 있습니다. 마지막에 솔루션의 수를 알고 싶다면 경로 데이터 구조를 조정하면됩니다.
* 검색을 찾으십시오. 그것은 당신의 친구입니다.