zoukankan      html  css  js  c++  java
  • 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
    ");
        else
            printf("%d
    ",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;
    }
    

      

  • 相关阅读:
    java如何实现以数据流的形式下载压缩包到本地?
    在用easyui中做CRUD功能时,当删除一行或多行数据后再点击修改会提示你选中了多行,如何解决这个bug了?
    windows中当你的键盘无法使用时我们可以用另一种方法哦
    Idea中如何将web项目打包成war包并放到tomcat中启动
    [CSS3] Use media query to split css files and Dark mode (prefers-color-scheme: dark)
    [PWA] Storage information for PWA application
    [HTML5] Native lazy-loading for the web
    [Dynamic Programming] 198. House Robber
    [Javascript] Sort by multi factors
    [Javascript] Keyword 'in' to check prop exists on Object
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4786933.html
Copyright © 2011-2022 走看看