Module: 動的プログラミングのパターン - 2


Problem

4 /5


ドワーフ

Theory Click to read/hide

免責事項: 以下に説明する方法は普遍的なものではありませんが、多くの場合、問題を解決したり、適切な解決策を見つけるのに役立ちます.

問題内の順列の存在を確認する必要がある場合、または一致する順列の数を見つける必要がある場合、または同様のものを見つける必要がある場合は、動的サブセット プログラミングの使用を検討する必要があります。

メインパラメータはビットマスクで、どの要素がすでに置換に含まれているか、どの要素が含まれていないかを示します。また、どの要素が最後に含まれたかを示す 2 番目のパラメータも必要になることがよくあります。

多くの場合、グラフ内のパスのコンテキストで順列が見られます。したがって、古典的な例であるハミルトン経路問題を考えてみましょう。
ハミルトニアン パスは、グラフの各頂点を 1 回だけ通過する単純なパスです。これは、単純に長さ n の順列として表すことができます (n は頂点の数です)。この順列内の順序は、このパス内の頂点が通過する順序を示します。

グラフ内のハミルトニアン パスの存在を確認するために、ダイナミクス dp[mask][last] を開始しましょう。マスク ビットマスクで 1 でマークされた頂点をバイパスし、最後の頂点に到達する単純なパスはありますか。
初期値は dp[2i][i] = true、残りは false になります。これは、いずれかの頂点から始まる空のパスが常に存在することを意味します。
dp[mask][last] の値を true にすると、「パスを延長する」という意味で、前方に遷移します。つまり、マスク内でゼロのマークが付いている頂点の数 (途中でまだ訪問していません) を探し、同時に最後の頂点からこの頂点までのエッジが存在する頂点の数を探します (パスは既存のエッジによって延長されます)。つまり、 dp[mask | 2k][k] = dp[mask][last] = true かつマスク & の場合は true 2k = 0 (頂点 k はまだ訪問されていません) そして最後にエッジがあります ->き
最終的に、オール 1 ビットマスクおよび任意の最後の頂点のパラメーターの dp に真の値があれば、ハミルトニアン パスが存在します。

Problem

ドワーフのクォークが宝の地図に出くわしたとき。宝物が見つかるマップ上に N 個のポイントがマークされています。すべての点には 1 から N までの番号が付けられています。点の各ペアについて、Quark はそれらを結ぶ道路の長さを認識しています。クォークはポイント 1 から検索を開始します。長い旅を始める前に、狡猾なドワーフは、彼の意見では宝物が存在しないと思われるポイントを取り消します。ポイント番号 1 が取り消されないことが保証されています。その後、Quark はマップ上の残りのすべてのポイントを通過するルートを選択します。ルートは同じポイントを 2 回以上通過しません。クォークは、交差していない点を結ぶ道路のみを歩くことができます。

Quark は、最小の長さのルートを選択したいと考えています。クォークにとっては、そのようなルートを見つける必要があります。

入力
最初の行には、1 つの整数 N (1 ≤ N ≤ 15) — が含まれています。マップ上にマークされたポイントの数。次の N 行には、ポイント間の距離が含まれています。 (i+1) 番目の行には、N 個の整数 di1、di2、diN が含まれます — i 番目のポイントから他のすべてのポイントまでの道路の長さ。 dij=dji、dii=0、0 ij ij <であることが保証されています。 100 . (N+2) 番目の行には、1 つの整数 Q (1 < Q ≤ 1000) が含まれています。このマップのポイントを削除するためのオプションの数。次の Q 行には、削除のオプションの説明が含まれています。説明は数字 C (0 ≤ C < N) — で始まります。クォークによれば、宝物がありえないポイントの数。次の C 数は、これらの点の数を示します。

インプリント
Q 行を印刷します。各行に 1 つの整数を出力します。ポイントを削除する対応するオプションを使用した最小ルートの長さ。
<頭> <本体>
# 入力 出力
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