題目描述
n個人在做傳遞物品的遊戲,編號為1-n。
即物品只能經過同乙個人一次,而且每次傳遞過程都有乙個代價;不同的人傳給不同的人的代價值之間沒有聯絡;
求當物品經過所有n個人後,整個過程的總代價最小是多少。
輸入
第一行為n,表示共有n個人(16>=n>=2);
以下為n*n的矩陣,第i+1行、第j列表示物品從編號為i的人傳遞到編號為j的人所花費的代價,特別的有第i+1行、第i列為-1(因為物品不能自己傳給自己),其他資料均為正整數(<=10000)。
(對於50%的資料,n<=11)。
輸出
乙個數,為最小的代價總和。
樣例輸入
2-1
9794
2724
-1
樣例輸出
2724
資料範圍限制提示50% n<=11
思路:
狀態壓縮 dp 是一種針對集合的 dp,可以用乙個整數對應的二進位制數表示乙個集合,用這個集合來表示當前的狀態,通過位運算來轉移狀態。與普通 dp 相比,狀態壓縮 dp 的轉移狀態比較複雜,由於一些特點可以使用乙個二進位制數來表示,從而達到了壓縮狀態的效果,其在 dp 思路上與普通 dp 基本類似。狀壓dp運用到一些位運算,大致如下:
關於位運算的高階:
三種常用的操作:
判斷x的第i位是否為1 if( x&(1<
將x的第i位改為1 x=x|1<
將x的最低位1去掉 x=x&(x-1);
回到本題……
題目大意:有n個人在傳球,可以從任意乙個人開始,任何乙個未接球的人,都可以作為下乙個接球的人,每兩個人之間傳球需要花費一些代價,問所有人都接到過球後的最小代價。
設f[st][i]表示當前狀態為st下,以i為當前的最後接球人的最小代價。
初始狀態: f[1所有的狀態的區間為1~(1當然必須這個人要是拿過球的,即(1<
j作為當前的最後持球人,他才能繼續往下傳,下乙個接球的人顯然也必須有乙個條件:他沒有接過球,即(1狀態轉移方程:f[i
∣(1<
][k]
=min
(f[i
∣(1<
][k]
,f[i
][j]
+a[j
][k]
);f[i|(1
i∣(1
<
][k]
=min
(f[i
∣(1<
][k]
,f[i
][j]
+a[j
][k]
);第i個狀態時,最後持球人為j,將球傳給了k,那麼新狀態為i|(1傳球結束後,這個狀態(1
#include
#include
#include
#include
#include
#include
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using
namespace std;
const
int max=
2147483647
;const
int n=
1e6;
int n,a[20]
[20],f[
1<<17]
[17],ans=max;
intmain()
vijos1456 最小總代價
描述 n 個人在做傳遞物品的遊戲,編號為1 n。遊戲規則是這樣的 開始時物品可以在任意一人手上,他可把物品傳遞給其他人中的任意一位 下乙個人可以傳遞給未接過物品的任意一人。即物品只能經過同乙個人一次,而且每次傳遞過程都有乙個代價 不同的人傳給不同的人的代價值之間沒有聯絡 求當物品經過所有 n 個人後...
Vijos 最小總代價 狀壓DP
描述 n個人在做傳遞物品的遊戲,編號為1 n。即物品只能經過同乙個人一次,而且每次傳遞過程都有乙個代價 不同的人傳給不同的人的代價值之間沒有聯絡 求當物品經過所有n個人後,整個過程的總代價是多少。格式 輸入格式 第一行為n,表示共有n個人 16 n 2 以下為n n的矩陣,第i 1行 第j列表示物品...
狀態壓縮動態規劃 最小總代價
乙個包含n個元素的集合,該集合的子集可以表示為從0 00 2n 12 n 1 2n 1 的是乙個十進位制整數。例如 一共有5個人,第0 3個人被選擇,就用 01001 2 01001 2 01001 2 表示,那麼該子集對應的十進位制數為9。此謂狀態壓縮。把傳遞過物品的人的集合壓縮為乙個整數i,用i...