乙個包含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...