HDU-4856 Tunnels (BFS+状压DP)

Problem Description

Bob is travelling in Xi’an. He finds many secret tunnels beneath the city. In his eyes, the city is a grid. He can’t enter a grid with a barrier. In one minute, he can move into an adjacent grid with no barrier. Bob is full of curiosity and he wants to visit all of the secret tunnels beneath the city. To travel in a tunnel, he has to walk to the entrance of the tunnel and go out from the exit after a fabulous visit. He can choose where he starts and he will travel each of the tunnels once and only once. Now he wants to know, how long it will take him to visit all the tunnels (excluding the time when he is in the tunnels).

Input

The input contains mutiple testcases. Please process till EOF.
For each testcase, the first line contains two integers N (1 ≤ N ≤
15), the side length of the square map and M (1 ≤ M ≤ 15), the number of
tunnels.
The map of the city is given in the next N lines. Each
line contains exactly N characters. Barrier is represented by “#” and
empty grid is represented by “.”.
Then M lines follow. Each line consists of four integers x1, y1, x2, y2, indicating there is a tunnel with entrence in (x1, y1) and exit in (x2, y2). It’s guaranteed that (x1, y1) and (x2, y2) in the map are both empty grid.

Output

For each case, output a integer indicating the minimal time Bob will use in total to walk between tunnels.
If it is impossible for Bob to visit all the tunnels, output -1.

Sample Input

5 4

....#

...#.

.....

.....

.....

2 3 1 4

1 2 3 5

2 3 3 1

5 4 2 1

Sample Output

7

题目大意:在一张nxn(n<16)的图中,"."表示空白区域,"#"表示障碍,每次移动的方向是上下左右之一,每移动一次耗时加1。有m条已知进口和出口的隧道,在隧道中移动不花时间。问要游览完所有的隧道最少需要的时间是多少?顺序自选。

题目分析:一看数据规模那么小,就想到是状压DP了。但要用BFS预处理出两两隧道之间的距离(起始隧道的出口与终止隧道的进口的距离)。定义状态dp(i,j)表示已经走过的隧道集合为i,并且当前在j位置时已经花掉的最小时间。则状态转移方程为dp(i|(1<<k),k)=min(dp(i|(1<<k),k),dp(i,j)+dist(j,k))。

代码如下:

# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;
const int INF=100000;
struct TT
{
    int sx,sy,ex,ey;
};
struct node
{
    int x,y,t;
    node(int _x,int _y,int _t):x(_x),y(_y),t(_t){}
};
TT t[15];
char mp[20][20];
int dist[20][20];
int vis[20][20],n,m,dp[1<<15][15];
int d[4][2]={{0,-1},{0,1},{-1,0},{1,0}};
int bfs(int sx,int sy,int ex,int ey)
{
    queue<node>q;
    memset(vis,0,sizeof(vis));
    vis[sx][sy]=1;
    q.push(node(sx,sy,0));
    while(!q.empty())
    {
        node u=q.front();
        q.pop();
        if(u.x==ex&&u.y==ey)
            return u.t;
        for(int i=0;i<4;++i){
            int nx=u.x+d[i][0],ny=u.y+d[i][1];
            if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&!vis[nx][ny]&&mp[nx][ny]!=‘#‘){
                vis[nx][ny]=1;
                q.push(node(nx,ny,u.t+1));
            }
        }
    }
    return INF;
}
void init()
{
    for(int i=0;i<m;++i)
        for(int j=0;j<m;++j)
            dist[i][j]=bfs(t[i].ex,t[i].ey,t[j].sx,t[j].sy);
}
void DP()
{
    int tot=1<<m;
    for(int i=0;i<tot;++i)
        for(int j=0;j<m;++j)
            dp[i][j]=INF;
    for(int i=0;i<m;++i)
        dp[1<<i][i]=0;
    for(int i=1;i<tot;++i){
        for(int j=0;j<m;++j){
            if(i&(1<<j))
                continue;
            int sta=i|(1<<j);
            for(int k=0;k<m;++k){
                if(i&(1<<k))
                    dp[sta][j]=min(dp[sta][j],dp[i][k]+dist[k][j]);
            }
        }
    }
    int ans=INF;
    for(int i=0;i<m;++i)
        ans=min(ans,dp[tot-1][i]);
    if(ans==INF)
        printf("-1\n");
    else
        printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;++i)
            scanf("%s",mp[i]+1);
        for(int i=0;i<m;++i)
            scanf("%d%d%d%d",&t[i].sx,&t[i].sy,&t[i].ex,&t[i].ey);
        init();
        DP();
    }
    return 0;
}

  

时间: 2024-11-13 06:28:19

HDU-4856 Tunnels (BFS+状压DP)的相关文章

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+状压DP)

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

hdu 3247 AC自动+状压dp+bfs处理

Resource Archiver Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)Total Submission(s): 2382    Accepted Submission(s): 750 Problem Description Great! Your new software is almost finished! The only thing left to

hdu 4856 Tunnels(bfs+状态压缩)

题目链接:hdu 4856 Tunnels 题目大意:给定一张图,图上有M个管道,管道给定入口和出口,单向,现在有人想要体验下这M个管道,问最短需要移动的距离,起点未定. 解题思路:首先用bfs处理出两两管道之间移动的距离,然后后用状态压缩求出最短代价,dp[i][j],i表示的已经走过的管道,j是当前所在的管道. #include <cstdio> #include <cstring> #include <queue> #include <algorithm&g

HDU 4924 Football Manager(状压DP)

题目连接 : http://acm.hdu.edu.cn/showproblem.php?pid=4924 题意 : n(<=20)个人选出11个人作为首发组成a-b-c阵容,每个人都有自己擅长的位置,并且每个人和其他人会有单向的厌恶和喜欢关系,每个人对于自己擅长的位置都有两个值CA和PA,有喜欢或者厌恶关系的两个人在一起也会影响整个首发的CA总值,要求选出一套阵容使得CA最大,或者CA一样的情况下PA最大. 思路 : 状压搞,dp[s]s的二进制表示20个人中选了那几个人,然后规定选进来的顺序

hdu 2825 aC自动机+状压dp

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5640    Accepted Submission(s): 1785 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

HDU 1074 Doing Homework(状压DP)

Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will r

HDU-3502-Huson&#39;s Adventure Island(BFS+状压DP)

Problem Description A few days ago, Tom was tired of all the PC-games, so he went back to some old FC-games. "Hudson's Adventure Island" was his favorite which he had played thousands of times. But to his disappointed, the more he played, the mo

HDU 3681 BFS&amp;状压DP&amp;二分

N*M矩阵,从F点出发,走完所有的Y点,每走一格花费1点电量,走到G点时,电量充满,D不可到达,问起始时的最小满电量可以走完所有Y,Y和G一共最多15个 先BFS出所有的F,Y,G之间的最短距离. 然后二分起始电量,对每个电量,做状压DP判断是否可行 #include "stdio.h" #include "string.h" #include "queue" using namespace std; int inf=0x3f3f3f3f; in