문제

각 노드가 최대 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) 순서로 포함됩니다. 이 시점과 별도로 따를 필요는 없지만 합병 할 수 있습니다. 마지막에 솔루션의 수를 알고 싶다면 경로 데이터 구조를 조정하면됩니다.

* 검색을 찾으십시오. 그것은 당신의 친구입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top