狀態壓縮動態規劃 最小總代價

2021-10-08 14:50:34 字數 1404 閱讀 2858

乙個包含n個元素的集合,該集合的子集可以表示為從0

00~2n−

12^n - 1

2n−1

的是乙個十進位制整數。 例如:一共有5個人,第0、3個人被選擇,就用(

01001)2

(01001)_2

(01001

)2​表示,那麼該子集對應的十進位制數為9。此謂狀態壓縮。

把傳遞過物品的人的集合壓縮為乙個整數i,用i的二進位制表示這個集合。例如:一共有5個人,第0、3個人被傳遞過,就用(

01001)2

(01001)_2

(01001

)2​表示,該集合的十進位制表示為9。

f[i][j]表示當前傳遞過物品的人的集合為i、最後乙個傳遞到的人為j的情況下的最小代價。

因為j是最後乙個被傳遞到的人,也就是說j必須包含在集合i中,那麼合法狀態必須滿足(i >> j) & 1 != 0

如果能從j轉移到下乙個人k,那k必須不在集合i中,那麼必須滿足(i >> k) & 1 == 0

轉移方程為f[i | 1 << k][k] = min(f[i | 1 << k][k], f[i][j] + g[j][k])

因為開始時物品可以在任意一人手上,此時最小代價為0,所以f[1 << i][i] = 0,其它狀態為無窮大

o (n

×n×2

n)

o(n×n×2^n)

o(n×n×

2n)

狀態數:n×2

nn×2^n

n×2n

轉移次數: n

nn

#include #include using namespace std;

const int n = 20, m = 1 << n, inf = 0x3f3f3f3f;

int f[m][n];

int g[n][n];

int n;

int main()}}

}int res = inf;

//打擂台求所有人的傳遞過時最小值

for(int i = 0; i < n; i ++)

res = min(res, f[(1 << n) - 1][i]);

cout << res << endl;

return 0;

}

最小編輯代價(動態規劃)

在nowcoder上的題目,原題如下 對於兩個字串a和b,我們需要進行插入 刪除和修改操作將a串變為b串,定義c0,c1,c2分別為三種操作的代價,請設計乙個高效演算法,求出將a串變為b串所需要的最少代價。給定兩個字串a和b,及它們的長度和三種操作代價,請返回將a串變為b串所需要的最小代價。保證兩串...

最小編輯代價(動態規劃)

實現 對於不同的要求,主要是找到求dp i j 的規律。include include include include include include include using namespace std define max length 50 字串的最大長度 求出dp i j 代表從str1 ...

最小代價樹(動態規劃)

description 以下方法稱為最小代價的字母樹 給定一正整數序列,例如 4,1,2,3,在不改變量的位置的條件下把它們相加,並且用括號來標記每一次加法所得到的和。例如 4 1 2 3 5 5 10。除去原數不4,1,2,3之外,其餘都為中間結果,如5,5,10,將中間結果相加,得到 5 5 1...