hdu-4856 Tunnels 状压DP

http://acm.hdu.edu.cn/showproblem.php?pid=4856

有若干管道,每个管道有且只能走一次,而地图可以随意走。

那么可以先处理每个管道间的最短路(不要考虑借助其他管道的情况,因为随后我们用压位的方式可以很轻松地处理不走重复管道的问题,这里不应该引入过多干扰)。

随后我们把每个管道是否访问看作01序列,dp[i][j]看着当前处于j号管道,访问状态为i。然后预先加入当且访问一个管道的m个状态,做bfs即可(很多人做了三重循环,个人不太会那么犀利的操作,只会bfs直观一点hhh,不过两个bfs搞得代码很丑就是了)。

#include <iostream>
#include <string>
#include <queue>
#include <cstring>
using namespace std;
const int N=1005;
const int inf=99999999;
int n,m;
string mp[20];
int vis[20][20];
struct p
{
    int x,y;
};
p in[20],ou[20];
int d[20][20];
struct node
{
    int s;
    p po;
};
int dir[4][2]={1,0,-1,0,0,1,0,-1};
bool ok(p px)
{
    if(px.x<0||px.y<0)return 0;
    if(px.x>=n||px.y>=n)return 0;
    if(vis[px.y][px.x]) return 0;
    if(mp[px.y][px.x]=='#')return 0;
    return 1;
}
void bfs(int np)
{
    queue<node> q;
    node ii;
    ii.s=0;
    ii.po=ou[np];
    q.push(ii);
    memset(vis,0,sizeof vis);
    vis[ii.po.y][ii.po.x]=1;
    d[np][np]=0;
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        for(int i=0;i<m;i++)
        {
            if(i==np)continue;
            if(now.po.x==in[i].x&&now.po.y==in[i].y)
                d[np][i]=now.s;
        }
        for(int i=0;i<4;i++)
        {
            node nx=now;
            nx.s++;
            nx.po.x+=dir[i][0];
            nx.po.y+=dir[i][1];
            if(ok(nx.po))
            {
                vis[nx.po.y][nx.po.x]=1;
                q.push(nx);
            }
        }
    }
}
int dp[40000][20];
int numid[20];
struct dpx
{
    int d;
    int po;
    dpx(int dd,int pp)
    {
        d=dd;
        po=pp;
    }
};
int main()
{
    cin.sync_with_stdio(false);
    while(cin>>n>>m)
    {
        for(int i=0;i<n;i++)
            cin>>mp[i];
        for(int i=0;i<m;i++)
        {
            cin>>in[i].y>>in[i].x>>ou[i].y>>ou[i].x;
            in[i].x--;
            in[i].y--;
            ou[i].x--;
            ou[i].y--;
        }
        for(int i=0;i<m;i++)
            for(int j=0;j<m;j++)
                d[i][j]=inf;
        for(int i=0;i<m;i++)
            bfs(i);
        for(int i=0;i<(1<<m);i++)
            for(int j=0;j<m;j++)
                dp[i][j]=inf;
        int dx=1;
        queue<dpx> q;
        int ad=0;
        for(int i=0;i<m;i++)
        {
            ad+=dx;
            dp[dx][i]=0;
            numid[i]=dx;
            q.push(dpx(dx,i));
            dx<<=1;
        }
        while(!q.empty())
        {
            dpx now=q.front();
            q.pop();
            for(int i=0;i<m;i++)
            {
                if((now.d&numid[i])==0)
                {
                    dpx nx=now;
                    nx.d+=numid[i];
                    nx.po=i;
                    if(dp[nx.d][nx.po]>dp[now.d][now.po]+d[now.po][nx.po])
                    {
                        dp[nx.d][nx.po]=dp[now.d][now.po]+d[now.po][nx.po];
                        q.push(nx);
                    }
                }
            }
        }
        int ans=inf;
        for(int i=0;i<m;i++)
            ans=min(ans,dp[(1<<m)-1][i]);
        if(ans>=inf)cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-01-25 15:20  Luke_Ye  阅读(196)  评论(0编辑  收藏  举报