正文

Zoj 2279 In the Mirror2008-02-13 18:21:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/niao0311/32646.html

分享到:

一道很好的搜索题。WA一次,原因是二进制hash开的太小。 一般求最短步数的问题,大多采用BFS,当终点与当前节点的XY值相等时输出,本题也不例外。难点在于,镜子的状态如何处理。 注意到镜子的数目<10,每一镜子仅有两种状态 \ 和/ 。因此将每一面镜子左右视为0与1,得到二进制编码的值hash,存入BFS中的节点。最大节点状态为2^10*10*10=102400 ,时间和空间上完全满足要求。 这里总共有三个102400的数组。一个队列Q,一个step存放某节点的步数,一个sight进行预处理,记录下当镜子出于某种状态hash下,每个点是否能够访问。 代码太长,格式放不上来,辛辛苦苦打了半天没了,只好帖原文。里面有一些相当有用的技巧,比如对于每一面镜子i的开关操作(0置为1,1置为0)是2^i xor hash,又比如对方向的处理数组与处理函数——这就和马路边的城管一样,常见,而且实用。但是方向函数看代码是看不懂的,需要自己分析一下。 #include <cstdio>#include <string> char a[11][11];int N, M, num_m, num_b, step[10][10][1024], sight[10][10][1024], ans;int dir[4][2] ={ { 0, 1 }, { 1, 0 }, { 0, -1 }, { - 1, 0 }};int p[11] ={ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; typedef struct{ int x, y, dir, step, h;} Bat;Bat sb, eb, Mirror[12], Q[102410], B[100]; int init ();void bfs ();void proc ( int );int redir ( int, int, int );  //计算方向void print (); int main (){ //freopen ( "in.txt", "r", stdin ); while ( init () ) {  bfs ();  print (); } return 0;} int init (){ num_m = num_b = 0, ans = -1; if ( scanf ( "%d%d", &N, &M ) == EOF ) {  return 0; } gets ( a[0] ); int i, j;  for ( i = 0; i < N; i ++ ) {  gets ( a[i] );  for ( j = 0; j < M; j ++ )  {   //终始点   if ( a[i][j] == 'S' )   {    sb.x = i, sb.y = j, a[i][j] = '.';   }   if ( a[i][j] == 'E' )   {    eb.x = i, eb.y = j, a[i][j] = '.';   }   //镜子   if ( a[i][j] == '/' )   {    Mirror[num_m].x = i, Mirror[num_m].y = j, Mirror[num_m ++].dir = 0;   }   if ( a[i][j] == '\\' )   {    Mirror[num_m].x = i, Mirror[num_m].y = j, Mirror[num_m ++].dir = 1;   }   //蝙蝠   if ( a[i][j] == '>' )   {    B[num_b].x = i, B[num_b].y = j, B[num_b ++].dir = 0;   }   if ( a[i][j] == 'v' )   {    B[num_b].x = i, B[num_b].y = j, B[num_b ++].dir = 1;   }   if ( a[i][j] == '<' )   {    B[num_b].x = i, B[num_b].y = j, B[num_b ++].dir = 2;   }   if ( a[i][j] == '^' )   {    B[num_b].x = i, B[num_b].y = j, B[num_b ++].dir = 3;   }  } } //printf ( "%d %d\n", num_b, num_m ); memset ( step, 0xff, sizeof ( step ) ); memset ( sight, 0xff, sizeof ( sight ) ); return 1;} void bfs (){ //预处理所有的镜面反射状况 int hash = 0, i, j, k, tx, ty, td; for ( i = 0; i < num_m; i ++ ) {  hash += Mirror[i].dir ? p[i] : 0; } step[sb.x][sb.y][hash] = 0; //保存初始值 for ( k = 0; k < p[num_m]; k ++ ) {  proc ( k );  //处理镜面 p[num_m]种情况  for ( i = 0; i < N; i ++ )  {   for ( j = 0; j < M; j ++ )   {    if ( a[i][j] != '.' )    {     sight[i][j][k] = 0;    }   }  }  for ( i = 0; i < num_b; i ++ )  {   tx = B[i].x, ty = B[i].y, td = B[i].dir;   tx += dir[td][0], ty += dir[td][1];   while ( tx >= 0 && tx < N && ty >= 0 && ty < M && a[tx][ty] != '#' )   {    sight[tx][ty][k] = 0;    td = redir ( tx, ty, td );    tx += dir[td][0], ty += dir[td][1];   }  }  //pt ( k ); } //BFS int op, ed, tstep, th;  proc ( hash ); step[sb.x][sb.y][hash] = 0; if ( sight[sb.x][sb.y][hash] == 0 )  return; for ( op = -1, ed = 0, Q[0].x = sb.x, Q[0].y = sb.y, Q[0].step = 0, Q[0].h = hash; op ++ < ed; ) {  if ( Q[op].x == eb.x && Q[op].y == eb.y )  {   ans = Q[op].step;   break;  }  tstep = Q[op].step + 1, th = Q[op].h;  for ( i = 0; i < 4; i ++ )  {   tx = Q[op].x + dir[i][0], ty = Q[op].y + dir[i][1];   if ( tx >= 0 && tx < N && ty >= 0 && ty < M && sight[tx][ty][th] )   {    if ( step[tx][ty][th] == -1 )    {     step[tx][ty][th] = tstep;     Q[++ ed].x = tx, Q[ed].y = ty, Q[ed].h = th, Q[ed].step = tstep;    }   }  }  for ( i = 0; i < num_m; i ++ )  {   th = Q[op].h ^ p[i], tx = Q[op].x, ty = Q[op].y;   if ( sight[tx][ty][th] && step[tx][ty][th] == -1 )   {    step[tx][ty][th] = tstep;    Q[++ ed].x = tx, Q[ed].y = ty, Q[ed].h = th, Q[ed].step = tstep;   }  } }} void proc ( int hash ){ int i; int x = hash; for ( i = 0; i < num_m; i ++ ) {  Mirror[i].dir = hash & 1;  //printf ( "%d", Mirror[i].dir );  a[Mirror[i].x][Mirror[i].y] = Mirror[i].dir ? '\\' : '/';  hash >>= 1; } //pt ( x );} int redir ( int x, int y, int d ){ if ( a[x][y] == '/' ) {  return 3 - d; } if ( a[x][y] == '\\' ) {  return d ^ 1; } return d;} void print (){ if ( ans == -1 ) {  printf ( "poor\n" ); } else {  printf ( "%d\n", ans ); }}  

阅读(3226) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册