<<表示左移,如a<<1表示将a的二进制左移一位,加一个0,&0xff表示取最后8个字节,如a&0xff表示取a表示的二进制中最后8个数字组成一个新的二进制数,| 运算符表示对2个数的二进制位进行比较,只要2个之中有一个这个位是1,则2者进行或运算之后得到的那个二进制数相应的位也是1。
因此,可以将3个数进行左移操作,然后再进行或运算,最后得到一个数,然后就可以通过这个数进行右移操作再进行&0xff操作就能得到原来的数。由于直接对二进制进行操作,因而速度极快。
有读者可能会说可以直接开一个结构体,将3个数都归属于一个结构体中,这样当然可以,不过速度远慢于上述操作。
对于POJ3523---The Morning after Halloween(UVa 1601)题目,运用结构体的运行时间是4672MS,而用第一个方法的运行时间是3719MS。所以明显第一个方法远远优于结构体方法。
以下为题目完整代码:
///本题可以通过对空白格进行构图,从而减少广搜时所需的操作时间。可以对每个空格进行编号,然后记录开始状态和结束状态,从开始状态对图进行广搜 #include<cstdio> #include<queue> #include<cstring> #include<cctype> using namespace std; const int maxs=20; const int maxn=150; const int dr[]= {1,-1,0,0,0}; /// 4 moves, plus "no move" const int dc[]= {0,0,1,-1,0}; inline int ID(int a, int b, int c) { return (a<<16)|(b<<8)|c;///由于int 类型保存8个字节,所以这个操作将a放到了最前面的8个字节,b放到了中间的8个字节,c放到了最后的8个字节 } int s[3],t[3];///s表示开始位置,t表示终点位置 int degree[maxn],G[maxn][5]; inline bool conflict(int a, int b, int a2, int b2) { return a2 == b2 || (a2 == b && b2 == a);///第一个表示a,b进入同一空格,第二个表示2者交换位置 } int d[maxn][maxn][maxn];///表示所走的总步数 int bfs() { queue<int> q; q.push(ID(s[0],s[1],s[2])); memset(d,-1,sizeof(d)); d[s[0]][s[1]][s[2]]=0; while(!q.empty()) { int u=q.front(); q.pop(); int a=(u>>16)&0xff,b=(u>>8)&0xff,c=u&0xff; if(a==t[0]&&b==t[1]&&c==t[2]) return d[a][b][c]; for(int i=0;i<degree[a];i++)///从第一个鬼开始,查找连通的空格 { int a2=G[a][i]; for(int j=0;j<degree[b];j++) { int b2=G[b][j]; if(conflict(a,b,a2,b2)) continue; for(int k=0;k<degree[c];k++) { int c2=G[c][k]; if(conflict(a, c, a2, c2)) continue; if(conflict(b, c, b2, c2)) continue; if(d[a2][b2][c2]!=-1) continue;///判断是否被访问过 d[a2][b2][c2]=d[a][b][c]+1; q.push(ID(a2,b2,c2)); } } } } return -1; } int main() { int w,h,n; while(~scanf("%d%d%d\n",&w,&h,&n)&&w) { char maze[20][20]; for(int i = 0; i < h; i++) fgets(maze[i], 20, stdin); int cnt,x[maxn],y[maxn],id[maxs][maxs];///cnt 用于计数,id数组用于记录空格所处位置及其编号 cnt=0; for(int i=0; i<h; i++) for(int j=0; j<w; j++) if(maze[i][j]!='#') { x[cnt]=i; y[cnt]=j; id[i][j]=cnt; if(islower(maze[i][j])) s[maze[i][j]-'a']=cnt; else if(isupper(maze[i][j])) t[maze[i][j]-'A']=cnt; cnt++; } for(int i=0; i<cnt; i++) ///建图 { degree[i]=0; for(int dir=0; dir<5; dir++) { int nx=x[i]+dr[dir]; int ny=y[i]+dc[dir]; if(maze[nx][ny]!='#') G[i][degree[i]++]=id[nx][ny]; } } ///加入假鬼,使3种情况都能按照3个鬼的bfs进行,由于假鬼开始就待在终点,所以不会对结果产生影响 if(n <= 2) { degree[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; } if(n <= 1) { degree[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; } printf("%d\n",bfs()); } return 0; }
浙公网安备 33010602011771号