代码改变世界

UVA - 10911 Forming Quiz Teams

2017-07-22 16:11  tlnshuju  阅读(302)  评论(0编辑  收藏  举报

题目大意:有 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;
}