YbtOJ练习:广搜 2 射击问题
这道题的难点在于如何判断在某个时刻巨龙能否打中猎物,如果每一次巨龙走完都要check一次效率太低,而注意到猎物是不动的,我们可以初始化出能打中猎物的点,只要巨龙移动到这些位置,就完成搜索。
#include<bits/stdc++.h> #define x first #define y second using namespace std; typedef pair<int,int> PII; const int N=1600; int n,m; bool vis[N][N],useful[N][N]; char g[N][N]; int dis[N][N]; int x,y,x1,y2;//猎物,巨龙 int ans; PII q[N*N]; int dx[8]={-1,1,0,0,-1,-1,1,1}; int dy[8]={0,0,-1,1,-1,1,-1,1}; void make_useful() { // (x,y) useful[x][y]=true; bool flag; /* for(int i=1;i<x;i++) //同一列 { if(g[i][y]=='X') flag=true; if(flag) useful[i][y]=false; else useful[i][y]=true; } flag=false; for(int i=x+1;i<=n;i++) { if(g[i][y]=='X') flag=true; if(flag) useful[i][y]=false; else useful[i][y]=true; } flag=false; for(int i=1;i<y;i++) //同一行 { if(g[x][i]=='X') flag=true; if(flag) useful[x][i]=false; else useful[x][i]=true; } flag=false; for(int i=y+1;i<=m;i++) { if(g[x][i]=='X') flag=true; if(flag) useful[x][i]=false; else useful[x][i]=true; } //flag=false;*/ for(int i=0;i<8;i++) { flag=false; int nx=x+dx[i],ny=y+dy[i]; while(nx>0&&nx<=n&&ny>0&&ny<=m) { if(g[nx][ny]=='X') flag=true; if(flag) useful[nx][ny]=false; else useful[nx][ny]=true; nx+=dx[i];ny+=dy[i]; } } } bool bfs() { memset(vis,0,sizeof(vis)); int hh=0,tt=0; q[0]=make_pair(x1,y2); dis[x1][y2]=0; vis[x1][y2]=1; while(hh<=tt) { PII tmp=q[hh++]; if(useful[tmp.x][tmp.y]) { ans=dis[tmp.x][tmp.y]; return true; } for(int i=0;i<4;i++) { int nx=tmp.x+dx[i],ny=tmp.y+dy[i]; if(g[nx][ny]=='X') continue; if(nx<1||nx>n||ny<1||ny>m) continue; if(vis[nx][ny]) continue; dis[nx][ny]=dis[tmp.x][tmp.y]+1; vis[nx][ny]=1; q[++tt]=make_pair(nx,ny); } } return false; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",g[i]+1); while(~scanf("%d%d%d%d",&x,&y,&x1,&y2)&&x&&y&&x1&&y2) { memset(useful,0,sizeof(useful)); make_useful(); if(bfs()) printf("%d\n",ans); else puts("Impossible!"); } return 0; }