Module: Các mẫu trong Lập trình động - 2


Problem

4 /5


Quỷ lùn

Theory Click to read/hide

Tuyên bố miễn trừ trách nhiệm: Phương pháp được mô tả bên dưới không phổ biến nhưng thường có thể giải quyết vấn đề hoặc giúp bạn tìm ra giải pháp phù hợp.

Nếu bạn cần kiểm tra sự tồn tại của một hoán vị trong một bài toán hoặc tìm số lượng các hoán vị khớp với nhau hoặc điều gì đó tương tự, thì bạn nên cân nhắc sử dụng lập trình tập hợp con động.

Tham số chính sẽ là một mặt nạ bit, sẽ hiển thị phần tử nào đã được đưa vào hoán vị và phần tử nào chưa. Thông số thứ hai cũng thường được yêu cầu cho biết phần tử nào được đưa vào sau cùng.

Thông thường, các hoán vị có thể được nhìn thấy trong ngữ cảnh của các đường dẫn trong biểu đồ. Theo đó, chúng ta hãy xem xét một ví dụ cổ điển - bài toán đường đi Hamilton.
Đường đi Hamilton là đường đi đơn đi qua mỗi đỉnh của đồ thị đúng một lần. Nó có thể được biểu diễn đơn giản dưới dạng một hoán vị độ dài n, trong đó n là số đỉnh. Thứ tự trong hoán vị này sẽ cho biết thứ tự đi qua các đỉnh trong đường dẫn này.

Để kiểm tra sự hiện diện của một đường dẫn Hamilton trong biểu đồ, hãy bắt đầu động lực học dp[mask][last] - có một đường dẫn đơn giản bỏ qua các đỉnh được đánh dấu bằng các đỉnh trong mặt nạ bit mặt nạ và kết thúc ở đỉnh cuối cùng không.
Các giá trị ban đầu sẽ là dp[2i][i] = true, còn lại là false, nghĩa là luôn có một đường đi trống bắt đầu từ bất kỳ đỉnh nào.
Có giá trị true trong dp[mask][last] chúng ta sẽ thực hiện chuyển tiếp về phía trước, theo nghĩa "mở rộng đường dẫn". Đó là, chúng tôi sẽ tìm kiếm số lượng đỉnh được đánh dấu bằng 0 trong mặt nạ (chúng tôi chưa truy cập chúng trên đường đi) và đồng thời sao cho có một cạnh từ đỉnh cuối cùng đến đỉnh này (đường đi phải được mở rộng bởi một cạnh hiện có). Đó là, chúng tôi làm dp[mask | 2k][k] = true nếu dp[mask][last] = true AND mask & 2k = 0 (đỉnh k chưa được thăm) Và có một cạnh cuối cùng -> k.
Cuối cùng, một đường dẫn Hamilton tồn tại nếu có một giá trị thực trong dp cho các tham số của bitmask tất cả một và bất kỳ đỉnh cuối cùng nào.

Problem

Khi người lùn Quark bắt gặp một bản đồ kho báu. Có N điểm được đánh dấu trên bản đồ nơi có thể tìm thấy kho báu. Tất cả các điểm được đánh số từ 1 đến N. Đối với mỗi cặp điểm, Quark biết độ dài của con đường nối chúng. Quark bắt đầu cuộc tìm kiếm của mình từ điểm số 1. Trước khi bắt đầu cuộc hành trình dài của mình, người lùn xảo quyệt đã gạch bỏ những điểm mà theo ý kiến ​​\u200b\u200bcủa anh ta, không thể có kho báu. Đảm bảo rằng điểm số 1 không bao giờ bị gạch bỏ. Sau đó, Quark chọn một số tuyến đường đi qua tất cả các điểm còn lại trên bản đồ. Tuyến đường không đi qua cùng một điểm nhiều lần. Một quark chỉ có thể đi trên những con đường nối các điểm không giao nhau.

Quark muốn chọn một tuyến đường có độ dài tối thiểu. Cần phải tìm một lộ trình như vậy cho Quark.

Đầu vào
Dòng đầu tiên chứa một số nguyên N (1 ≤ N ≤ 15) — số điểm được đánh dấu trên bản đồ. N dòng tiếp theo ghi khoảng cách giữa các điểm. Dòng thứ (i+1) chứa N số nguyên di1,di2, diN — độ dài các con đường từ điểm thứ i đến tất cả các điểm khác. Đảm bảo rằng dij=dji, dii=0 và 0 <dij < 100 . Dòng thứ (N+2) chứa một số nguyên Q (1 < Q ≤ 1000) — số tùy chọn xóa điểm cho bản đồ này. Q dòng sau đây chứa mô tả về các tùy chọn xóa. Mô tả bắt đầu bằng số C (0 ≤ C < N) — số điểm mà theo Quark, kho báu không thể có được. Các số C tiếp theo cho biết số lượng của các điểm này.

Dấu ấn
In Q dòng. Trong mỗi dòng in một số nguyên — chiều dài của tuyến đường tối thiểu với tùy chọn xóa điểm tương ứng.
Ví dụ
<đầu>
# Đầu vào Đầu ra
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