hdu4856(bfs + 状态压缩)

来源:互联网 发布:东京 泡泡 上门 知乎 编辑:程序博客网 时间:2024/05/21 22:21

题意:一个n*n的网格,"#"表示障碍物,m个隧道,每个隧道都有个出口和入口,为走遍所有隧道的最短时间,一分钟走一个网格。绝对是到好题,N很少,一开始用bfs+dfs做,超时了,因为dfs时的时间复杂度是15!。

解题思路:把模型转换一下就变成了,n个隧道,每个隧道之间的距离为c[i][j](这个是通过bfs求出来的),然后就用状压缩DP解,dp[i][j]表示当前状态为i所在的隧道是j,

状态转移dp[(1<<k)+j][k] = min(dp[(1<<k)+j][k],c[i][j]+dp[i][j]),然后初始化dp为inf,dp[1<<i][i] = 0。到这里题目就可以做出来了

代码如下:

#include<iostream>#include<algorithm>#include<queue>#include<stdio.h>#include<math.h>#include<cstring>#include<string>#define N 20#define inf 0x3f3f3f3f#define pi acos(-1.0)#define eps 10e-6using namespace std;char a[N][N];struct node{    int x,y;}s[N],e[N];int dp[1<<16][N];queue<node> q;int vis[N][N];int tag[N];int n,m,ans,flag;int c[N][N];int dist[N][N];int d[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};void bfs(int x,int y)//求每个隧道出口到其他隧道入口的最近距离{    for(int i = 0; i < n; i++)        for(int j = 0; j < n; j++)            dist[i][j] = inf;    memset(vis,0,sizeof(vis));    while(!q.empty()) q.pop();    node temp;    temp.x = x;    temp.y = y;    q.push(temp);    vis[x][y] = 1;    dist[x][y] = 0;    while(!q.empty())    {        node now = q.front();        q.pop();        int i;        for(i = 0; i < 4; i++)        {            int tempx = now.x + d[i][0];            int tempy = now.y + d[i][1];            temp.x = tempx;            temp.y = tempy;            if(tempx < 0 || tempx >= n || tempy < 0 || tempy >= n || vis[tempx][tempy] || a[tempx][tempy] == '#')                continue;            vis[tempx][tempy] = 1;            dist[tempx][tempy] = dist[now.x][now.y]+1;            q.push(temp);        }    }}int main(){    while(scanf("%d%d",&n,&m) != EOF)    {        int i, j,k;        for(i = 0; i < n; i++)            scanf("%s",a[i]);        for(i = 0; i < m; i++){            scanf("%d%d%d%d",&s[i].x,&s[i].y,&e[i].x,&e[i].y);            s[i].x--;s[i].y--;e[i].x--;e[i].y--;        }        memset(c,0,sizeof(c));        for(i = 0; i < m; i++)        {            bfs(e[i].x,e[i].y);            for(j = 0; j < m; j++)                if(i != j)                    c[i][j] = dist[s[j].x][s[j].y];        }        for(i = 0; i < (1<<m); i++)            for(j = 0; j < m; j++)                dp[i][j] = inf;//注意初始化        for(i = 0; i < m; i++)            dp[1<<i][i] = 0;        for(i = 0; i < (1<<m); i++)//关键在这里            for(j = 0; j < m; j++)                if(i&(1<<j))                    for(k = 0; k < m; k++)                    {                        if(k == j) continue;                        if((i&(1<<k)) == 0)                            dp[i+(1<<k)][k] = min(dp[i+(1<<k)][k],c[j][k]+dp[i][j]);                    }        int ans = inf;        for(i = 0; i < m; i++)            if(dp[(1<<m)-1][i] < ans)                ans = dp[(1<<m)-1][i];        if(ans >= inf) printf("-1\n");        else printf("%d\n",ans);    }    return 0;}

0 0
原创粉丝点击