Ural 1912 - Passing through Walls 阅读理解+BFS+高效Hash

   题意:  1和2这两个人在一个矩形的地图中。他们行走的过程中必须时刻保持联系,保持联系的意思是两个人与至少一个'+'相邻。图中有"."代表脆弱的墙,两个人可以穿过这类墙,而'-','|'表示坚固的墙,两人无法穿过。问两人都走出矩形一共最少需要穿过多少个脆弱的墙。

   注意!!!题目要咱求的不是最小步数~而是穿过的墙个数!!...也就是说..当一个人走出去一个..就不需要再穿过任何墙了..但根据题目要求,还是必须保持两个人相邻。

   题意理解透了~这题就不难了..关键是Hash..我之前用set判重..时间超完.其实用一个bool数组就行了..

   H[y][x][i]代表当1在(x,y)时..2在1的i方向..250*250*8~完全ok!!



Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<set>
#include<queue>
#include<stack>
#define ll long long 
#define oo 1000000007
#define MAXN 300
using namespace std; 
struct node
{
       int y1,x1,y2,x2,dis;
}h,p;
int n,m,way[8][2]={{-1,-0},{1,0},{0,1},{0,-1},{-1,1},{-1,-1},{1,1},{1,-1}};
char arc[MAXN<<1][MAXN<<1];
queue<node> myqueue; 
bool H[300][300][8];
bool hash(node h)
{
       int i,j;
       for (i=0;i<8;i++) 
          if (h.y1+way[i][0]==h.y2 && h.x1+way[i][1]==h.x2)  break; 
       if (H[h.y1][h.x1][i]) return false;
       H[h.y1][h.x1][i]=true;
       return true;
}
bool legal(node h)
{
       int i,j;
       for (i=0;i<8;i++) 
          if (h.y1+way[i][0]==h.y2 && h.x1+way[i][1]==h.x2) return true; 
       if (h.x1==h.x2 && h.y1==h.y2) return false;
       return false;
}
bool isans(node h)
{
       int p=0;
       if (h.x1<1 || h.y1<1 || h.x1>m || h.y1>n) p++;
       if (h.x2<1 || h.y2<1 || h.x2>m || h.y2>n) p++;
       if (p==2) return true;
       return false;
}
bool canuse(node h)
{
       if (h.x1<0 || h.y1<0 || h.x2<0 || h.y2<0) return false;
       if (h.x1>m+2 || h.y1>n+2 || h.x2>m+2 || h.y2>n+2) return false;
       return true;
}
int BFS()
{
       int i,j;
       node p;
       while (!myqueue.empty()) myqueue.pop(); 
       memset(H,0,sizeof(H));
       h.dis=0;
       hash(h); 
       myqueue.push(h);
       while (!myqueue.empty())
       {
               h=myqueue.front();
               myqueue.pop();
               if (isans(h)) break;  
               for (i=0;i<4;i++)
               {
                      p=h; 
                      p.y1+=way[i][0],p.x1+=way[i][1];
                      if (canuse(p) && arc[h.y1*2+way[i][0]][h.x1*2+way[i][1]]=='.') 
                      { 
                            if (legal(p) && hash(p))
                            {
                                   if ((p.x1<1 || p.y1<1 || p.x1>m || p.y1>n) && (h.x1<1 || h.y1<1 || h.x1>m || h.y1>n))
                                       p.dis=h.dis;
                                   else
                                       p.dis=h.dis+1;
                                   myqueue.push(p); 
                            }
                      }
                      p=h; 
                      p.y2+=way[i][0],p.x2+=way[i][1];
                      if (canuse(p) && arc[h.y2*2+way[i][0]][h.x2*2+way[i][1]]=='.') 
                      { 
                             if (legal(p) && hash(p))
                             {
                                   if ((p.x2<1 || p.y2<1 || p.x2>m || p.y2>n) && (h.x2<1 || h.y2<1 || h.x2>m || h.y2>n))
                                       p.dis=h.dis;
                                   else
                                       p.dis=h.dis+1;
                                   myqueue.push(p); 
                             }
                      }
               } 
       }
       if (isans(h)) return h.dis;
       return -1;       
}
int main()
{
       int i,j; 
       while (~scanf("%d%d",&n,&m))
       { 
               gets(arc[0]);   
               for (i=1;i<=2*n+1;i++) gets(arc[i]+1); 
               for (i=0;i<=2*n+3;i++) arc[i][0]=arc[i][2*m+2]='.';
               for (i=0;i<=2*m+3;i++) arc[0][i]=arc[2*n+2][i]='.';
               for (i=1;i<=2*n+1;i++)
                  for (j=1;j<=2*m+1;j++)
                  {
                         if (arc[i][j]=='1') h.y1=i>>1,h.x1=j>>1,arc[i][j]=' ';
                         if (arc[i][j]=='2') h.y2=i>>1,h.x2=j>>1,arc[i][j]=' ';
                  }
               i=BFS();
               if (i==-1) printf("Death\n");
                       else  printf("%d\n",i);
       }
       return 0;
}
/*
2 2
+-+-+
. .1|
+-+-+
|2. .
+.-.+

3 3
+-+.+-+
. .1| |
+-+-+-+
| .2. .
+-+-+-+
. . . .
+-+-+-+

3 3
+-+.+-+
. |2| |
+.+-+.+
| |1. .
+.+-+-+
. . . .
+-+-+-+

3 5
+-+-+-+-+-+
| | . . . .
+-+.+-+-+-+
| |1. . . |
+-+-+-+-+-+
| |2. . . .
+-+-+-+-+-+

6 2
+.+-+
| | | 
+.+.+
| | |
+.+.+
| | |
+.+.+
| | |
+.+.+
| | |
+.+.+
|1|2|
+-+.+

ans
3
10
5
Death
7
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值