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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值