1. 程式人生 > >COCI 2016/2017 Round #3,November 25th,2017 Portal [bfs+Dijkstra]

COCI 2016/2017 Round #3,November 25th,2017 Portal [bfs+Dijkstra]

題意:給你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]);
}