• 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;
    }
    
    

  • 相关阅读:
    docker 可视化面板工具 protainer
    Docker 镜像及容器命令
    linux 系统上通过docker容器技术部署Nginx,whereis nginx
    Linux CentOS7 系统下安装及卸载Docker 及 配置阿里云镜像加速 及 Docker C/S架构
    Docker数据卷 Volume 挂载,容器路径与linux主机路径的一致性映射,mysql 实战
    什么是 JWT JSON WEB TOKEN ,理论部分
    2022 年最受瞩目的新特性 CSS @layer 到底是个啥?
    一道有意思的 CSS 面试题,FizzBu​​zz ~
    巧用 backgroundclip 实现超强的文字动效
    节点基于资源压力要驱逐pod时,pod的状态是什么?
  • 原文地址:https://www.cnblogs.com/csnd/p/12062948.html
Copyright © 2020-2023  润新知