COCI 2016/2017 Round #3,November 25th,2017 Portal [bfs+Dijkstra]
阿新 • • 發佈:2019-01-30
題意:給你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]); }