转自此博客

题目:刘汝佳《算法竞赛入门经典》,集合上的动态规划---最优配对问题 题意:空间里有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 }
View Code

相关文章: