题意:给你n*m图,这个图中有墙,起点,终点,一个人从起点开始往终点走,他有一把枪,可以对四个方向射击,射到的墙会产生传送门,地图上只能存在两个传送门,可以相互连通,求从C到F的最小步数。
题解:对于一个点来说,首先肯定是可以向四个方向走1步,然后假如用传送门的话,肯定是往一个方向射击,然后走到最近的墙射击然后传送,这样的话,我们需要预处理出所有点四个方向的墙的位置,与距离这个点最近的墙的位置,然后最短路跑出C到F 的距离。
AC代码:
#include<stdio.h>
#include<queue>
#include<stdlib.h>
#include<string.h>
#define INF 1000000005
using namespace std;
char a[505][505];
int n,m;
struct node
{
int x,y;
node(){}
node(int x,int y)
{
this->x=x;
this->y=y;
}
};
struct point
{
int x,y,w;
point(){}
point(int x,int y,int w)
{
this->x=x;
this->y=y;
this->w=w;
}
};
int dist[505][505],mark[505][505];
int len[505][505],fly[505][505][4][2];
int dir[4][2]={
{1,0},
{-1,0},
{0,1},
{0,-1}
};
priority_queue<point>QUE;
queue<node>que;
bool operator<(point a,point b)
{
return a.w>b.w;
}
void bfs()
{
memset(mark,0,sizeof(mark));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='#')
que.push(node(i,j)),mark[i][j]=1;
while(!que.empty())
{
node k=que.front();
que.pop();
for(int i=0;i<4;i++)
{
int dx=k.x+dir[i][0];
int dy=k.y+dir[i][1];
if(dx<=0||dy<=0||dx>n||dy>m||mark[dx][dy]||a[dx][dy]=='#')continue;
mark[dx][dy]=1;
len[dx][dy]=len[k.x][k.y]+1;
que.push(node(dx,dy));
}
}
}
void dij(node s)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dist[i][j]=INF,mark[i][j]=0;
dist[s.x][s.y]=0;
QUE.push(point(s.x,s.y,0));
while(!QUE.empty())
{
point k=QUE.top();
QUE.pop();
if(mark[k.x][k.y])continue;
mark[k.x][k.y]=1;
for(int i=0;i<4;i++)
{
int dx=k.x+dir[i][0];
int dy=k.y+dir[i][1];
if(dx<=0||dy<=0||dx>n||dy>m||mark[dx][dy]||a[dx][dy]=='#')continue;
if(dist[dx][dy]>k.w+1)
{
dist[dx][dy]=k.w+1;
QUE.push(point(dx,dy,dist[dx][dy]));
}
}
for(int i=0;i<4;i++)
{
int dx=k.x+fly[k.x][k.y][i][0];
int dy=k.y+fly[k.x][k.y][i][1];
if(dist[dx][dy]>k.w+len[k.x][k.y])
{
dist[dx][dy]=k.w+len[k.x][k.y];
QUE.push(point(dx,dy,dist[dx][dy]));
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",a[i]+1);
node s,e;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]=='C')s=node(i,j);
if(a[i][j]=='F')e=node(i,j);
}
bfs();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
fly[i][j][0][0]=fly[i-1][j][0][0]-1;
fly[i][j][3][1]=fly[i][j-1][3][1]-1;
if(a[i-1][j]=='#')fly[i][j][0][0]=0;
if(a[i][j-1]=='#')fly[i][j][3][1]=0;
}
for(int i=n;i>=1;i--)
for(int j=m;j>=1;j--)
{
fly[i][j][1][1]=fly[i][j+1][1][1]+1;
fly[i][j][2][0]=fly[i+1][j][2][0]+1;
if(a[i+1][j]=='#')fly[i][j][2][0]=0;
if(a[i][j+1]=='#')fly[i][j][1][1]=0;
}
dij(s);
if(dist[e.x][e.y]==INF)printf("nemoguce\n");
else printf("%d\n",dist[e.x][e.y]);
}