hdu 4856 Tunnels(bfs+状态压缩)

题目链接:hdu 4856 Tunnels

题目大意:给定一张图,图上有M个管道,管道给定入口和出口,单向,现在有人想要体验下这M个管道,问最短需要移动的距离,起点未定。

解题思路:首先用bfs处理出两两管道之间移动的距离,然后后用状态压缩求出最短代价,dp[i][j],i表示的已经走过的管道,j是当前所在的管道。

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;
const int maxn = 20;
const int INF = 0x3f3f3f3f;
const int dir[4][2] = { {0, 1}, {1, 0}, {-1, 0}, {0, -1} };

struct point {
    int x, y;
    point (int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }
};

struct pipe {
    point s, e;
} pi[maxn];

int N, M, d[maxn][maxn];
int dp[(1<<15)+5][maxn];
char g[maxn][maxn];

int bfs (point s, point e) {
    int vis[maxn][maxn];
    memset(vis, -1, sizeof(vis));

    queue<point> que;

    vis[s.x][s.y] = 0;
    que.push(s);

    while (!que.empty()) {
        point u = que.front();
        que.pop();

        if (u.x == e.x && u.y == e.y)
            return vis[u.x][u.y];

        for (int i = 0; i < 4; i++) {
            int x = u.x + dir[i][0];
            int y = u.y + dir[i][1];

            if (x <= 0 || x > N || y <= 0 || y > N)
                continue;

            if (vis[x][y] != -1 || g[x][y] == ‘#‘)
                continue;

            vis[x][y] = vis[u.x][u.y] + 1;
            que.push(point(x, y));
        }
    }
    return -1;
}

void init () {
    for (int i = 1; i <= N; i++)
        scanf("%s", g[i] + 1);

    memset(d, 0, sizeof(d));

    for (int i = 0; i < M; i++) {
        scanf("%d%d%d%d", &pi[i].s.x, &pi[i].s.y, &pi[i].e.x, &pi[i].e.y);

        for (int j = 0; j < i; j++) {
            d[i][j] = bfs(pi[i].e, pi[j].s);
            d[j][i] = bfs(pi[j].e, pi[i].s);
        }
    }
}

int solve () {
    memset(dp, INF, sizeof(dp));

    for (int i = 0; i < M; i++)
        dp[1<<i][i] = 0;

    for (int s = 0; s < (1<<M); s++) {

        for (int j = 0; j < M; j++) {
            if (dp[s][j] == INF)
                continue;

            for (int k = 0; k < M; k++) {
                if (s&(1<<k))
                    continue;

                if (d[j][k] == -1)
                    continue;

                dp[s|(1<<k)][k] = min(dp[s|(1<<k)][k], dp[s][j] + d[j][k]);
            }
        }
    }

    int ans = INF;
    for (int i = 0; i < M; i++)
        ans = min(ans, dp[(1<<M)-1][i]);
    return ans == INF ? -1 : ans;
}

int main () {
    while (scanf("%d%d", &N, &M) == 2) {
        init();

        printf("%d\n", solve());;
    }
    return 0;
}

hdu 4856 Tunnels(bfs+状态压缩)

时间: 2024-10-11 22:37:20

hdu 4856 Tunnels(bfs+状态压缩)的相关文章

hdu 5094 Maze bfs+状态压缩

Maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 642    Accepted Submission(s): 229 Problem Description This story happened on the background of Star Trek. Spock, the deputy captain of St

HDU 4856 Tunnels(bfs+状压dp)

题目大意:给你一个N*N的图让你到达所有的"."点,"#"不能通过,有m组每组有一个入口,一个出口,入口可以传送到出口,不知道经过m组的先后顺序,让你求出走过所有的"."的最小时间. 思路:先bfs出来所有的m之间的最短距离,然后dp[j][i] 表示,在j状态下开始第i步的最小路程,枚举找到一个最小的dp[1<<m - 1][i],就是最短距离,否则输出"-1". Tunnels Time Limit: 3000

hdu 4856 Tunnels BFS+不回起点的TSP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4856 注意到隧道是单向的 bfs求出距离以后套用TSP模板即可 注意日本人那本白书上的模板是最后要回到起点的 而本题并不回起点 具体的做法是建一个超级起点,跟图中每一个点都建花费为0的边,然后以之为起点跑一边即可 #include <cstring> #include <cstdlib> #include <cstring> #include <cmath> #

hdu 3001 Travelling (bfs+状态压缩)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3905    Accepted Submission(s): 1234 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

hdu 1429 (bfs+状态压缩)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5283    Accepted Submission(s): 1815 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)-- 这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了

HDU 1885Key Task(bfs + 状态压缩)

Key Task Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1529 Accepted Submission(s): 631 Problem Description The Czech Technical University is rather old - you already know that it celebrates 300

hdu 1429(BFS+状态压缩)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8379    Accepted Submission(s): 3008 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)--这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using

HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

题目链接:Resource Archiver 解析:n个正常的串.m个病毒串,问包括全部正常串(可重叠)且不包括不论什么病毒串的字符串的最小长度为多少. AC自己主动机 + bfs + 状态压缩DP 用最短路预处理出状态的转移.能够优化非常多 AC代码: #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <queue> us