**此部落格
題目:劉汝佳《演算法競賽入門經典》,集合上的動態規劃---最優配對問題
題意:空間裡有n個點p0,p1,...,pn-1,你的任務是把它們配成n/2對(n是偶數),使得每個點恰好在乙個點對中。所有點對中兩點的距離之和應盡量小。
狀態:d(i,s)表示把前i個點中,位於集合s中的元素兩兩配對的最小距離和
狀態轉移方程為:d(i,s)=min-}
1 #include 2 #include 3 #include 4 #include 5 #include 6view codeusing
namespace
std;
7const
int n = 20;8
const
int inf = 0x3f3f3f3f;9
double d[n + 5][(1
<< n) + 10
];10
struct
node
11node[n + 10
];14
double dist(int n1, int
n2)15
18int
main()
1926
for(int i = 0; i < n; i++)
2741}42
else
if(i != 0)43
46}47}
48 printf("
%.3lf\n
", d[n - 1][(1
<< n) - 1
]);49
return0;
50 }
狀態可以進行壓縮,i的值其實隱藏在s中,s中最高位為1的即為i,所以需要一次查詢,從n-1到0進行一次歷編即可,整個運算下來,平均查詢次數僅為2。而且方法二比方法一情況簡單很多,也比較容易理解。
1 #include 2 #include 3 #include 4 #include 5 #include 6view codeusing
namespace
std;
7const
int n = 20;8
const
int inf = 0x3f3f3f3f;9
double d[(1
<< n) + 10
];10
struct
node
11node[n + 10
];14
intn, s;
15double dist(int n1, int
n2)16
19void
input()
2025 s = 1
<
26 d[0] = 0;27
}28void
solve()
2941}42
intmain()
43
這道題用遞迴實現更好一些,因為只需要判斷n為偶數的情況,這就是遞迴運算的好處,而非遞迴則需要全部都進行一次運算。
1 #include 2 #include 3 #include 4 #include 5 #include 6view codeusing
namespace
std;
7const
int n = 20;8
const
int inf = 0x3f3f3f3f;9
double d[(1
<< n) + 10
];10
struct
node
11node[n + 10
];14
intn, s;
15double dist(int n1, int
n2)16
19void
input()
2026 s = 1
<
27//
memset(d, inf, sizeof(d)); 慎用emset()
28for(int i = 0; i < s; i++)
29 d[i] =inf;
30 d[0] = 0;31
32}33double dp(int
s)34
46int
main()
47
最優配對問題(集合上的動態規劃) 狀壓DP
題意 給出n個點的空間座標 n為偶數,n 20 把他們配成n 2對,問 怎樣配對才能使點對的距離和最小?題解 設dp s 為 狀態為s s代表著某個子集 時,它的最小距離和。1.對於乙個狀態s,首先要計算它減少兩個點後的狀態的最小距離和,然後當前狀態才能從這些狀態中轉移過來。2.如何轉移 對於狀態s...
最優配對問題(動態規劃)
空間裡有n個點p0,p1,p2.pn 1,你的任務是把他們配成n 2對 n是偶數 使得每個點恰好在乙個點對中。所有點的距離之和應該盡量小。n 20.定義狀態d i s 為前i個點中,位於集合s的元素兩兩配對的最小距離,則狀態轉移方程就是 d i,s min 其中 pipj 表示兩點之間的距離。邊界是...
最優批處理問題 動態規劃
在一台超級計算機上,編號為1,2,3 的n個作業等待批處理。批處理的任務就是將這n個作業分成若干批,每批包含相鄰的若干作業。從時刻0開始,分批加工這些作業。在每批作業開始前,機器需要啟動時間s,而完成這批作業所需的時間是單獨完成批中各個作業需要時間的總和。單獨完成第i個作業所需的時間是 ti,所需的...