bfs+状态压缩dp

题意:
      给你一个地图,问你吧所有的隧道都走完的最小费用,起点不固定,穿越隧道的时间不计,在隧道外边每移动一步花费一秒。

思路:
      先bfs求出所有dis[i][j](i的终点和j的起点的距离),然后在dp[i][j],i表示当
前状态(二进制压缩后的状态)j表示第几个点,则更新的方程也很简单
dp[i|(1<<(k-1))][j] = minn(本身,dp[i][j] + dis[j][k]);记得要加一个if((i|(1<<(k-1))) == 0)我个人认为没必要加,结果不加就wa,现在还在研究中,记得这种题目之前

做过很多,但之前的数据都很小,可以直接n!,写个搜索或者全排列暴力枚举过去,今天的这个过不去只能用dp了,之前没想过dp因为自己dp很水,想题很少会往dp上想,以后要加强了.

#include<stdio.h>
#include<string.h>
#include<queue>

#define INF 1000000000

using namespace std;

typedef struct
{
   int sx ,sy ,ex ,ey;
}SD;

typedef struct
{
   int x, y ,t;
}NODE;

SD sd[18];
NODE xin ,tou;
int dis[18][18];
char map[18][18];
int mark[18][18];
int dp[(1<<15)+10][18];
int dir[4][2] = {0 ,1 ,0 ,-1 ,1 ,0 ,-1 ,0};

bool ok(NODE a ,int n)
{
    return a.x >= 1 && a.x <= n && a.y >= 1 && a.y <= n 
    && !mark[a.x][a.y] && map[a.x][a.y] == '.';
}

int minn(int x ,int y)
{
   return x < y ? x : y;
}

int bfs(int sx ,int sy ,int ex ,int ey ,int n)
{
   memset(mark ,0 ,sizeof(mark));
   xin.x = sx ,xin.y = sy ,xin.t = 0;
   mark[sx][sy] = 1;
   queue<NODE>q;
   q.push(xin);
   while(!q.empty()) 
   {
      tou = q.front();
      q.pop();
      if(tou.x == ex && tou.y == ey)
      return tou.t;
      for(int i = 0 ;i < 4 ;i ++)
      {
         xin.x = tou.x + dir[i][0];
         xin.y = tou.y + dir[i][1];
         xin.t = tou.t + 1;
         if(ok(xin ,n))
         {
            mark[xin.x][xin.y] = 1;
            q.push(xin);
         }
      }
   }
   return INF;
}

int main ()
{
   int n ,m ,i ,j ,k;
   while(~scanf("%d %d" ,&n ,&m))
   {
      getchar();
      for(i = 1 ;i <= n ;i ++)
      {
         for(j = 1 ;j <= n ;j ++)
         scanf("%c" ,&map[i][j]);
         getchar();
      }
      for(i = 1 ;i <= m ;i ++)
      {
         scanf("%d %d %d %d" ,&sd[i].sx ,&sd[i].sy ,&sd[i].ex ,&sd[i].ey);
         for(j = i ;j <= m ;j ++)
         dis[i][j] = dis[j][i] = INF;
      }
      for(i = 1 ;i <= m ;i ++)
      for(j = i ;j <= m ;j ++)
      {
         if(i == j) 
         {
            dis[i][j] = 0;
            continue;
         }
         dis[i][j] = bfs(sd[i].ex ,sd[i].ey ,sd[j].sx ,sd[j].sy ,n);
         dis[j][i] = bfs(sd[j].ex ,sd[j].ey ,sd[i].sx ,sd[i].sy ,n);
      }
      for(i = 0 ;i <= (1 << m) ;i ++)
      for(j = 0 ;j <= m ;j ++)
      dp[i][j] = INF;
      
      for(i = 1 ;i <= m ;i ++)
      dp[1 << (i - 1)][i] = 0;
         
      for(i = 0 ;i < (1 << m) ;i ++)
      for(j = 1 ;j <= m ;j ++)
      //if(dp[i][j] != INF)
      for(k = 1 ;k <= m ;k ++)
      if(!(i & (1 << (k - 1))))//*****
      dp[i|(1<<(k-1))][k] = minn(dp[i|(1<<(k-1))][k] ,dp[i][j] + dis[j][k]);
      int ans = INF;
      for(i = 1 ;i <= m ;i ++)
      ans = minn(ans ,dp[(1<<m) - 1][i]);
      ans == INF ? puts("-1") : printf("%d
" ,ans);      
   }
   return 0;
}


原文地址:https://www.cnblogs.com/csnd/p/12062948.html