您的位置:首页 > 其它

HDU - 4281 Judges' response(MTSP)

2015-09-22 17:34 316 查看
题目大意:有n个点,第一个点是裁判的位置,其他的点是参赛者的位置。现在每个参赛者都要求裁判来答疑,裁判需要花Ci分钟对第i组进行答疑。已知每个裁判最多答疑M分钟,如何分配,才能使答疑的裁判的人数达到最少,如果可以分配的话,请求出裁判需要走的距离和的最小值

解题思路:状态压缩,然后预处理一下一个裁判的能答疑的组别

要判断需要多少个裁判的话,可以用背包+状压来解决

设dp[i]表示答疑i状态的组别需要的裁判的最小值

那么dp[i] = min(dp[i], dp[j + state[k]] + 1),其中i = j + state[k], (j & state[k]) == 0(因为一个组别只能由一个裁判来答疑),state[k]是一个裁判能处理第k个状态,前面已经预处理了

接着就是求最小距离和了,先求出一个裁判能处理的问题的最小距离和,然后再合并,这样就变成了先求一个人的TSP,然后再合并,就变成了MTSP问题了

用num[i]表示i状态下需要走的最小距离和

route[j][i]表示i状态下,最终停在j这个位置需要走的最小距离和

那么num[i] = min(num[i], route[j][i] + dis[j][0]),因为每个裁判都是从第1个点出发的

最后是合并

num[i] = min(num[i], num[j | 1] + num[k | 1])

其中j + k == i,因为每个裁判都是从1出来的,所以都要有一个1状态

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1 << 16;
const int M = 20;
const int INF = 0x3f3f3f3f;

int dis[M][M], x[M], y[M], c[M];
int state
, dp
, num
, route[M]
;
int n, m, tot;
bool ok
;

bool judge(int s) {
    int Sum = 0;
    for (int i = 0; i < n; i++)
        if (s & (1 << i)) Sum += c[i];

    return Sum <= m;
}

bool DP() {
    memset(dp, 0x3f, sizeof(dp));
    dp[0] = 0;

    for (int i = 0; i < tot; i++)
        for (int j = (1 << n) - 1; j >= 0; j--) {
            if (dp[j] == INF) continue;
            if ((j & state[i])) continue;
            dp[j + state[i]] = min(dp[j + state[i]], dp[j] + 1);
        }
    return dp[(1 << n) - 1] != INF;
}

void init() {
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
            dis[i][j] = dis[j][i] = ceil((sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]))));
    memset(num, 0x3f, sizeof(num));
    memset(route, 0x3f, sizeof(route));
    route[0][1] = 0;
}

int TSP() {
    init();
    for (int i = 0; i < (1 << n); i++) {
        if (ok[i]) {
            for (int j = 0; j < n; j++) {
                if (i & (1 << j)) num[i] = min(num[i], route[j][i] + dis[j][0]);
                for (int k = 0; k < n; k++) {
                    if (!(i & (1 << k))) {
                        route[k][i | (1 << k)] = min(route[k][i | (1 << k)], route[j][i] + dis[j][k]);
                    }
                }
            }
        }
    }
    for (int i = 1; i < (1 << n); i++) {
        if (i & 1) {
            for (int j = i & (i - 1); j > 0; j = i & (j - 1)) {
                num[i] = min(num[i], num[(i - j) | 1] + num[j | 1]);
            }
        }
    }
    return num[(1 << n) - 1];
}

int main() {
    while (scanf("%d%d", &n, &m) != EOF) {

        for (int i = 0; i < n; i++)
            scanf("%d%d", &x[i], &y[i]);

        for (int i = 0; i < n; i++)
            scanf("%d", &c[i]);

        tot = 0;
        for (int i = 0; i < (1 << n); i++) {
            ok[i] = judge(i);
            if (ok[i]) state[tot++] = i;
        }

        if (!DP())  {
            printf("-1 -1\n");
        }
        else {
            printf("%d %d\n", dp[(1 << n) - 1], TSP());
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: