`
jishublog
  • 浏览: 872136 次
文章分类
社区版块
存档分类
最新评论

HDU 4281 Judges' response

 
阅读更多

状态压缩dp,经典MTSP问题,第一问比较容易求,先求出满足情况的状态放在了mov里面,然后模拟0-1背包的过程求出最少用多少judge。第二问就比较复杂了,第二问要求我们算出最短的时间,即最短总路程。这样的话就比较难求了。。。第二问看了一下网上大神的代码才懂的。。。汗。。。第二问,dt[i][j],表示当状态为i(注意:i & 1 == 1)时, 最后一个走过的节点是j时最短路径, best[i] 表示状态完成状态 i 需要的最短路径。然后具体实现还是看代码吧。。。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>

#define SL strlen
#define PB push_back
#define LL long long
#define INF 0X3f3f3f3f
#define CLR(a, b) memset(a, b, sizeof(a))

using namespace std;

const int N = 17;

struct Point
{
    int x, y;
}p[N];

int dp[1 << N], c[N];
int dt[1 << N][N], best[1 << N];
int g[N][N];
vector<int> mov;
int n, m, i, j, k;

int len(Point a, Point b)
{
    return ceil(sqrt((double)(a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)));
}

bool ok(int k)
{
    int ret = 0; j = 0;
    while(k)
    {
        if(k & 1)
        {
            ret += c[j];
        }
        k >>= 1;
        j ++;
    }
    return ret <= m;
}

void input()
{
    for(i = 0; i < n; i ++)
    {
        scanf("%d%d", &p[i].x, &p[i].y);
    }
    for(i = 0; i < n; i ++)
    {
        scanf("%d", &c[i]);
    }
}

void work()
{
    for(i = 0; i < n; i ++)
    {
        for(j = 0; j < n; j ++)
        {
            g[i][j] = len(p[i], p[j]);
        }
    }
    mov.clear();
    for(i = 1; i < (1 << n); i ++)
    {
        if(ok(i)) mov.PB(i);
    }
}

bool solve()
{
    CLR(dp, INF);
    dp[0] = 0;
    for(i = 0; i < mov.size(); i ++)
    {
        for(j = (1 << n) - 1; j >= 1; j --)
        {
            if((j & mov[i]) == mov[i])
            {
                dp[j] = min(dp[j], dp[j ^ mov[i]] + 1);
            }
        }
    }
    if(dp[(1 << n) - 1] == INF) { printf("-1 ");return 0; }
    //else printf("%d ", dp[(1 << n) - 1]); return 1;
}

void TSP()
{
    CLR(best, INF);
    CLR(dt, INF);
    dt[1][0] = 0;
    for(i = 0; i < mov.size(); i ++)
    {
        for(j = 0; j < n; j ++)
        {
            if((1 << j) & mov[i])
            {
                best[mov[i]] = min(best[mov[i]], dt[mov[i]][j] + g[j][0]);
                for(k = 0; k < n; k ++)
                {
                    if(!((1 << k) & mov[i]))
                    {
                        dt[mov[i] | (1 << k)][k] = min(dt[mov[i] | (1 << k)][k], dt[mov[i]][j] + g[j][k]);
                    }
                }
            }
        }
    }
    for(i = 1; i < (1 << n); i ++)
    {
        if(i & 1) for(j = i & (i - 1); j; j = i & (j - 1))
        {
            best[i] = min(best[i], best[j] + best[(i ^ j) | 1]);
        }
    }
    printf("%d\n", best[(1 << n) - 1]);
}

int main()
{
    //freopen("input.txt", "r", stdin);
    while(scanf("%d%d", &n, &m) != EOF)
    {
        input();
        work();
        if(solve()) TSP();
        else puts("-1");
    }
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics