HDU 3920

来源:互联网 发布:linux 串口can总线驱动 编辑:程序博客网 时间:2024/05/18 00:36

    这题时间卡得太紧,状态DP不是随随便便能过。有一个优化,比如说:001111,110011,111100 -> 111111 其实效果都是一样的,所以每次状态转移时确保把第一个'0'变成'1'。现在不变,最终也要变,而且效果是一样的。这不过是个"迟早"的问题...
    优化前:000000 -> 110000, 101000, 100100, 100010, 100001, 011000, 010100, 010010, 010001, 001100, 001010, 001001, 000110, 000101, 000011。
    优化后:000000 -> 110000, 101000, 100100, 100010, 100001。
    这样,状态转移数就大大减少了。

#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <memory.h>#include <string>#include <vector>#include <map>#include <set>#include <queue>#include <algorithm>#include <iostream>#define ll long longusing namespace std;const int inf = 1000000000;const int N = 20;struct Point {    int x, y;} pt[N], st;double dp[1<<20];double dis[20][20];double cst[20];int que[1<<20], head, tail;double get_dis(const Point &a, const Point &b) {    double dx = a.x - b.x;    double dy = a.y - b.y;    return sqrt(dx * dx + dy * dy);}bool cmp(const Point &a, const Point &b) {    return get_dis(st, a) < get_dis(st, b);}int main() {    int T, C, n, i, j, a, b, x, y;    double v;    scanf("%d", &T);    for (C = 1; C <= T; C++) {        scanf("%d %d", &st.x, &st.y);        scanf("%d", &n); n *= 2;        for (i = 0; i < n; i++)            scanf("%d %d", &pt[i].x, &pt[i].y);        sort(pt, pt + n, cmp);        for (i = 0; i < n; i++) {            cst[i] = get_dis(st, pt[i]);            for (j = i + 1; j < n; j++)                dis[i][j] = get_dis(pt[i], pt[j]);        }        for (i = 1; i < (1 << n); i++)            dp[i] = inf;        head = 0; tail = -1;        que[++tail] = 0;        dp[0] = 0.0;        while (head <= tail) {            a = que[head++];            for (x = 0; x < n; x++)                if (!(a & (1 << x)))                    break;            for (y = x + 1; y < n; y++)                if (!(a & (1 << y))) {                    b = (a | (1 << x) | (1 << y));                    v = cst[x] + dis[x][y] + dp[a];                    if (dp[b] > v) {                        if (dp[b] == inf) que[++tail] = b;                        dp[b] = v;                    }                }        }        printf("Case #%d: ", C);        printf("%.2lf\n", dp[(1<<n)-1]);    }    return 0;}

原创粉丝点击