HDU 3920

    這題時間卡得太緊,狀態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 long

using 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章