题目大意:有 2 * n 个点,使其组成 n 对,求 n 对点集的最小距离之和.
解题思路:由于 2 * n 最大才 20,完全可以由数字的位来表示,每一个数字表示一个状态,然后才去记忆化搜索的方式得出结果。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int N;
double DP[1 << 17], dis[20][20];
double cal(int x, int y) {
return sqrt(x * x + y * y);
}
double DPS(int S) {
if (DP[S] || !S)
return DP[S];
int i;
for (i = N - 1; i >= 0; i--)
if (S & (1 << i)) break;
DP[S] = 0x3f3f3f3f;
for (int j = i - 1; j >= 0; j--)
if (S & (1 << j))
DP[S] = min(DP[S], dis[i][j] + DPS(S ^ (1 << i) ^ (1 << j)));
return DP[S];
}
int main() {
int x[20], y[20], kase = 0;
while (scanf("%d", &N), N) {
N <<= 1;
for (int i = 0; i < N; i++)
scanf("%*s%d%d", &x[i], &y[i]);
for (int i = 0; i < N; i++)
for (int j = i + 1; j < N; j++)
dis[j][i] = cal(x[i] - x[j], y[i] - y[j]);
memset(DP, 0, sizeof(DP));
printf("Case %d: %.2lf\n", ++kase, DPS((1 << N) - 1));
}
return 0;
}
时间: 2024-10-24 19:21:08