hdu4856(状态压缩)

来源:互联网 发布:剑三抓马坐标数据下载 编辑:程序博客网 时间:2024/05/01 15:16

题目:1010 Tunnels
链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856
题意:给定一个n*n的迷宫,迷宫有障碍物,然后给出一些在这个迷宫的地下通道(相当于传送门,进入入口就直接到出口),问走过所有通道一次,最少的时间消耗是多少
        详细见样例吧!

思路:状态压缩+bfs,首先bfs求出所有通道的出口到所有通道的入口的最短距离。然后定义dp[i][j],表示最后一个走的通道是第i个,已经走过的通道是j里面二进制位是1的,
        比如说dp[2][01011],此时的i是2,j是11(十进制),表示选了1 2 4 通道,而且第二通道是最后一个选的!这样就可以状态转移了,这里说的二进制第几位是从后面开始数的
        dp[j][i] = min(dp[j][i], dp[k][i ^ (1 << (j - 1))] + dis[k][j]);   其中转移的时候要满足j不等于k,且i的二进制位的j和k位已经是1了。



#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <iostream>using namespace std;#define N 20char s[N][N];const int inf = (1 << 25);int dp[20][1 << 15];int n, m;struct no{    int id, x1, y1, x2, y2;}e[N];int st[N][N];struct node{    int x, y, step;};bool vis[N][N];int dis[N][N];int dir[][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };bool ok(int x, int y){    if (x >= 1 && x <= n && y > 0 && y <= n) return true;    return false;}void BFS(int x, int y, int id){    queue<node> Q;    node now, next;    now.x = x;    now.y = y;    now.step = 0;    Q.push(now);    memset(vis, false, sizeof(vis));    vis[x][y] = true;    while (!Q.empty())    {        now = Q.front();        Q.pop();        if (st[now.x][now.y])        {            for (int i = 1; i <= m; i++)            if (now.x == e[i].x1 && now.y == e[i].y1)                dis[id][e[i].id] = (id == e[i].id ? inf : now.step);        }        for (int i = 0; i < 4; i++)        {            next.x = now.x + dir[i][0];            next.y = now.y + dir[i][1];            next.step = now.step + 1;            if (ok(next.x, next.y) && !vis[next.x][next.y] && s[next.x][next.y] != '#')            {                vis[next.x][next.y] = true;                Q.push(next);            }        }    }}int main(){    while (scanf("%d%d", &n, &m) != EOF)    {        for (int i = 1; i <= n; i++)            scanf("%s", s[i] + 1);        memset(st, 0, sizeof(st));        for (int i = 1; i <= m; i++)        {            scanf("%d%d%d%d", &e[i].x1, &e[i].y1, &e[i].x2, &e[i].y2);            st[e[i].x1][e[i].y1] = i;            e[i].id = i;        }        for (int i = 1; i <= m; i++)        for (int j = 1; j <= m; j++)            dis[i][j] = inf;        for (int i = 1; i <= m; i++)//bfs处理        {            BFS(e[i].x2, e[i].y2, e[i].id);        }        for (int i = 0; i <= m; i++)        {            for (int j = 0; j < (1 << n); j++)dp[i][j] = inf;        }        for (int i = 1; i <= m; i++)dp[i][1 << (i - 1)] = 0;//开始选的时候任意,这个时候时间都是0        for (int i = 0; i < (1 << m); i++)        {            for (int j = 1; j <= m; j++)            {                for (int k = 1; k <= m; k++)                {                    if (k == j)continue;                    if (((1 << (j - 1))&i) && ((1 << (k - 1))&i))//i的二进制位的j和k位已经是1了                                  dp[j][i] = min(dp[j][i], dp[k][i ^ (1 << (j - 1))] + dis[k][j]);                }            }        }        int res = inf;        for (int i = 1; i <= m; i++)res = min(res, dp[i][(1 << m) - 1]);        if (res >= inf)puts("-1");        else printf("%d\n", res);    }}


0 0
原创粉丝点击