Module: 동적 프로그래밍의 패턴 - 2


Problem

4 /5


난쟁이

Theory Click to read/hide

고지 사항: 아래에 설명된 방법은 보편적이지 않지만 종종 문제를 해결하거나 올바른 솔루션을 찾는 데 도움이 될 수 있습니다.

문제에서 순열의 존재를 확인해야 하거나 일치하는 순열의 수 또는 이와 유사한 것을 찾아야 하는 경우 동적 하위 집합 프로그래밍 사용을 고려해야 합니다.

기본 매개변수는 순열에 이미 포함된 요소와 포함되지 않은 요소를 표시하는 비트마스크입니다. 마지막으로 포함된 요소를 나타내는 두 번째 매개변수도 종종 필요합니다.

종종 순열은 그래프의 경로 컨텍스트에서 볼 수 있습니다. 따라서 고전적인 예인 해밀턴 경로 문제를 살펴보겠습니다.
해밀턴 경로는 그래프의 각 정점을 정확히 한 번 통과하는 단순 경로입니다. 길이 n의 순열로 간단하게 표현할 수 있습니다. 여기서 n은 정점의 수입니다. 이 순열 내의 순서는 이 경로의 꼭지점을 통과하는 순서를 나타냅니다.

그래프에서 Hamiltonian 경로의 존재를 확인하기 위해 역학을 시작하겠습니다.
초기 값은 dp[2i][i] = true이고 나머지는 false입니다. 즉, 정점에서 시작하는 빈 경로가 항상 있음을 의미합니다.
dp[mask][last] 값이 true이면 "경로 확장"이라는 의미에서 앞으로 전환합니다. 즉, 우리는 마스크에서 0으로 표시된 정점의 수를 찾고(아직 도중에 방문하지 않았음) 마지막에서 이 정점까지의 가장자리가 있는지 확인합니다(경로는 반드시 기존 가장자리로 확장). 즉, dp[mask | 2k][k] = dp[mask][last] = true AND mask & 2k = 0(정점 k는 아직 방문하지 않았음) 그리고 마지막에 에지가 있음 -> 케이.
궁극적으로, 모든 비트 마스크와 마지막 정점의 매개 변수에 대한 dp에 참 값이 있는 경우 해밀턴 경로가 존재합니다.

Problem

드워프 Quark가 보물지도를 발견했습니다. 지도에는 보물을 찾을 수 있는 N개의 지점이 표시되어 있습니다. 모든 포인트는 1부터 N까지 번호가 매겨져 있습니다. 각 포인트 쌍에 대해 Quark는 포인트를 연결하는 도로의 길이를 알고 있습니다. Quark는 1번 지점부터 검색을 시작합니다. 긴 여행을 시작하기 전에 교활한 드워프는 보물이 있을 수 없다고 생각하는 지점을 지웁니다. 포인트 번호 1이 절대 지워지지 않는다는 것이 보장됩니다. 그런 다음 Quark는 지도에 남아 있는 모든 지점을 통과하는 일부 경로를 선택합니다. 경로는 동일한 지점을 두 번 이상 통과하지 않습니다. 쿼크는 교차하지 않은 지점을 연결하는 길만 걸을 수 있습니다.

Quark은 최소 길이의 경로를 선택하려고 합니다. 쿼크는 그런 루트를 찾아야 합니다.

입력
첫 번째 줄에는 하나의 정수 N(1 ≤ N ≤ 15)이 포함됩니다. 지도에 표시된 포인트의 수. 다음 N 줄에는 점 사이의 거리가 포함됩니다. (i+1)번째 줄에는 N개의 정수 di1,di2, diN — i번째 지점에서 다른 모든 지점까지의 도로 길이. dij=dji, dii=0 및 0 <dij < 100 . (N+2)번째 줄은 하나의 정수 Q(1 < Q < 1000)를 포함합니다. 이 맵의 포인트 삭제 옵션 수. 다음 Q 행에는 삭제 옵션에 대한 설명이 포함되어 있습니다. 설명은 숫자 C(0 < C < N)로 시작합니다. Quark에 따르면 보물이 될 수 없는 지점의 수입니다. 다음 C 번호는 이러한 포인트의 번호를 제공합니다.

출판물
Q 라인을 인쇄합니다. 각 줄에 하나의 정수를 인쇄합니다. 포인트를 삭제하는 해당 옵션이 있는 최소 경로의 길이.
<헤드> <몸>
# 입력 출력
1 3
0  45 10
45 0  30
10 30 0
2
0
1 3
40
45
2 5
0  14 20 17 14
14 0  15 19 18
20 15 0  15 16
17 19 15 0  14
14 18 16 14 0
2
3 5 4 3
0
14
58