ビットマスキングと動的計画法を使用して問題を解決するビットマスキングと動的計画法
ビットマスキングの基本
前回はビットマスクの割付動作について簡単に紹介しましたが、問題を解決する前に、ビットマスクの値演算とチェック動作を紹介します。
値下げ操作:
b&!(1 << i)
例:
取i = 1、(1 << i)= 00010
!(1 << i)= 11101(各ビットを反転)
b = 01010
b&!(1 << i)= 01010&11101 = 01000(1ビットの値が削除されました)
動作確認:
b&(1 << i)
例:
取i = 1、(1 << i)= 00010
b = 01010
b&(1 << i)= 01010&000010 = 00010(結果は0ではありません)この場合、チェックビットには値があります。つまり、子にはチェックされた値が含まれます。
ビットマスキングと動的計画法の問題を解決する
トピック:
合計N個のタスクをN人に割り当てる必要があり、各人がタスクを完了し、N x Nマトリックスが与えられ、cost [i] [j]はi番目の人がjを完了するためのコストを表します-番目のタスク。次に、タスクを割り当てるための最もコストのかからないソリューションを見つける必要があります。
暴力的な解決策:
assign(N, cost)
for i = 0 to N
assignment[i] = i
res = INFINITY
for j= 0 to factorial(N)
total_cost = 0
for i = 0 to N
total_cost = total_cost + cost[i][assignment[i]]
res = min(res, total_cost)
generate_next_greater_permutation(assignment)
return res
強引なソリューションは、すべての配置をトラバースしてから、最小コストの値を返します。その時間計算量はO(N!)です。
次に、ビットマスキングと動的計画法のアイデアで問題を解決してみてください:
定義関数dp =(k、mask)
kは、最初のk人(タスク0〜k-1)にタスクが割り当てられていることを示し、maskは現在のマスクワードを示します。
k番目のタスクを割り当てる場合、dpを動的に検索するプロセスでは、状態方程式は次のようになります
。dp(k + 1、マスク|(1 << i))= min(dp(k + 1、マスク|(1 << i)))、dp(k、mask)+ cost [k] [i])
上記の式のkは、マスクワードの「1」の数(設定されたマスクワードの数)であることがわかります。割り当てられたタスクの数はkと同じ意味であるため、上記の式は次のように簡略化できます
。dp(mask |(1 << i))= min(dp(mask |(1 << i)、 dp(マスク)+ cost [x] [i](xはマスク内の1の数)
したがって、解決策は次のとおりです。
assign(N, cost)
for i = 0 to power(2,N)
dp[i] = INFINITY
dp[0] = 0
for mask = 0 to power(2, N)
x = count_set_bits(mask)
for j = 0 to N
if jth bit is not set in i
dp[mask | (1 << j)] = min(dp[mask | (1 << j)], dp[mask] + cost[x][j])
return dp[power(2, N) - 1]
上記のアルゴリズムの時間計算量はO(2 n n)であり、空間計算量はO(2 n)です。
アルゴリズムで何も理解できない場合は、コメント欄に質問してください。理解できるように最善を尽くします。
この記事はハッカーアース経由で言及しています:動的計画法/ビットマスキング