zoukankan      html  css  js  c++  java
  • 状压BFS

    ​题意:1个机器人找几个垃圾,求出最短路径。

    状压BFS,这道题不能用普通BFS二维vis标记数组去标记走过的路径,因为这题是可以往回走的,而且你也不能只记录垃圾的数量就可以了,因为它有可能重复走同一个垃圾。其实解决的办法就是把vis标记数组开到3维,用来存每次走的状态。再通过位运算即可。

    下面是2中常见的位运算操作:

    1、加入某一个垃圾:rubblish | =( 1 << i );

         eg: 0001 | 0100 =0101 ;

    2、进行垃圾匹配 :if( (  rubblish & ( 1 << i )  ) = = 0 ) continue;(注意括号的位置)

         eg:  0010 &1001=0  不匹配;

                0010 & 1011=1;可以匹配。

    谨记:以后像这种找垃圾、找钥匙去开门、可以跨越障碍求最短路径等等的题目,就可以考虑用状压BFS。(一般这些垃圾。钥匙不会超过10个,因为那样三维数组存不下)

    还有这题也可以用TSP去解。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define INF 0x3f3f3f3f
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 bool vis[21][21][1<<10];//vis数组存的是垃圾的状态
     8 char g[21][21];
     9 int key[21][21];//垃圾种类
    10 int ans=INF;
    11 int n,m,sx,sy;
    12 int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
    13 int C;
    14 struct mask
    15 {
    16     int x,y,key,step;
    17     mask(int x,int y,int key,int step):x(x),y(y),key(key),step(step){};
    18 };
    19 bool check(int a,int b){return 0<=a&&a<m&&0<=b&&b<n;}
    20 //判断是否找到所有的垃圾
    21 bool OK(int mask)
    22 {
    23    for(int i=0;i<C;i++)
    24    {
    25        if(mask&1<<i);
    26        else return false;
    27    }
    28    return true;
    29 }
    30 int bfs()
    31 {
    32     queue<mask>q;
    33     while(q.size())q.pop();
    34     q.push(mask(sx,sy,0,0));
    35     memset(vis,false,sizeof(vis));
    36       vis[sx][sy][0]=true;
    37     while(q.size()){
    38     mask tmp=q.front();q.pop();
    39     if(OK(tmp.key))
    40     {
    41         ans=min(ans,tmp.step);
    42     }
    43     for(int i=0;i<4;i++)
    44     {
    45         int nx=tmp.x+dx[i];
    46         int ny=tmp.y+dy[i];
    47         int nkey=tmp.key;
    48         if(g[nx][ny]!='x'&&check(nx,ny)&&!vis[nx][ny][nkey])
    49         {
    50             if(g[nx][ny]=='*')
    51             {
    52                 nkey|=key[nx][ny];
    53             }
    54             vis[nx][ny][nkey]=true;
    55             q.push(mask(nx,ny,nkey,tmp.step+1));
    56           }
    57         }
    58     }
    59     return ans==INF?-1:ans;
    60 }
    61 int main()
    62 {
    63     while(~scanf("%d %d",&n,&m)){
    64         if(n==0&&m==0)break;
    65        C=0;
    66        ans=INF;
    67       memset(key,0,sizeof(key));
    68     for(int i=0;i<m;i++)
    69     {
    70         scanf("%s",g[i]);
    71         for(int j=0;j<n;j++)
    72         {
    73             if(g[i][j]=='o')
    74             {
    75                 sx=i;
    76                 sy=j;
    77             }
    78             if(g[i][j]=='*')
    79             {
    80                key[i][j]=1<<C++;//预处理,把要清理的垃圾存入key数组中,即把第C个垃圾加入到key中
    81             }
    82         }
    83     }
    84     printf("%d
    ",bfs());
    85   }
    86 }
    View Code
  • 相关阅读:
    codeforces 985 F. Isomorphic Strings
    Educational Codeforces Round 44
    codeforces 979D
    ARC060 Digit Sum II
    Iroha and Haiku II
    Unhappy Hacking II
    Just h-index 2018湘潭邀请赛
    [HAOI2007]理想的正方形
    P1231 教辅的组成
    最小割数学形式
  • 原文地址:https://www.cnblogs.com/zhgyki/p/8996414.html
Copyright © 2011-2022 走看看