题目:刘汝佳《算法竞赛入门经典》,集合上的动态规划---最优配对问题 题意:空间里有n个点P0,P1,...,Pn-1,你的任务是把它们配成n/2对(n是偶数),使得每个点恰好在一个点对中。所有点对中两点的距离之和应尽量小。状态:d(i,S)表示把前i个点中,位于集合S中的元素两两配对的最小距离和 状态转移方程为:d(i,S)=min{|PiPj|+d(i-1,S-{i}-{j}}
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <math.h> 5 #include <algorithm> 6 using namespace std; 7 const int N = 20; 8 const int INF = 0x3f3f3f3f; 9 double d[N + 5][(1 << N) + 10]; 10 struct Node 11 { 12 int x, y, z; 13 }node[N + 10]; 14 double dist(int n1, int n2) 15 { 16 return sqrt( double( (node[n1].x - node[n2].x) * (node[n1].x - node[n2].x) + (node[n1].y - node[n2].y) * (node[n1].y - node[n2].y) + (node[n1].z - node[n2].z) * (node[n1].z - node[n2].z))); 17 } 18 int main() 19 { 20 int n; 21 scanf("%d", &n); 22 for(int i = 1; i <= n; i++) 23 { 24 scanf("%d%d%d", &node[i].x, &node[i].y, &node[i].z); 25 } 26 for(int i = 0; i < n; i++) 27 { 28 for(int S = 0; S < (1 << (i + 1) ); S++) 29 { 30 if(S == 0) 31 d[i][S] = 0; 32 else 33 d[i][S] = INF; 34 if(S & (1 << i)) 35 { 36 for(int j = 0; j < i; j++) 37 { 38 if(S & (1 << j) ) 39 d[i][S] = min(d[i][S], dist(i, j) + d[i - 1][S ^ (1 << i) ^ (1 << j)]); 40 } 41 } 42 else if(i != 0) 43 { 44 d[i][S] = d[i - 1][S]; 45 } 46 } 47 } 48 printf("%.3lf\n", d[n - 1][(1 << n) - 1]); 49 return 0; 50 }