1021 ObstacleCourse障碍训练课 优先队列+bfs+转弯
链接:https://ac.nowcoder.com/acm/contest/26077/1021
来源:牛客网
题目描述
考虑一个 N x N (1 <= N <= 100)的有1个个方格组成的正方形牧场。有些方格是奶牛们不能踏上的,它们被标记为了’x’。例如下图:
. . B x .
. x x A .
. . . x .
. x . . .
. . x . .
贝茜发现自己恰好在点A处,她想去B处的盐块舔盐。缓慢而且笨拙的动物,比如奶牛,十分讨厌转弯。尽管如此,当然在必要的时候她们还是会转弯的。对于一个给定的牧场,请你计算从A到B最少的转弯次数。开始的时候,贝茜可以使面对任意一个方向。贝茜知道她一定可以到达。
输入描述:
第 1行: 一个整数 N 行
2..N + 1: 行 i+1 有 N 个字符 (‘.’, ‘x’, ‘A’, ‘B’),表示每个点的状态。
输出描述:
行 1: 一个整数,最少的转弯次数。
分析
和1020一样
#include<bits/stdc++.h> using namespace std; const int N=1e6,M=110; typedef pair<int,int>PII; int h[N],e[N],ne[N],w[N],dist[N],idex,n,m,End,dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; bool st[N]; map<PII,int>mp; char room[M][M]; int res=0x3f3f3f3f; void add(int a,int b,int c){ e[idex]=b; ne[idex]=h[a]; w[idex]=c; h[a]=idex++; } void Dijkstra(int s){ priority_queue<PII,vector<PII>,greater<PII> >q; memset(dist,0x3f,sizeof(dist)); memset(st,0,sizeof(st)); dist[s]=0; q.push({0,s}); while(!q.empty()){ int pos=q.top().second; q.pop(); if(st[pos])continue; st[pos]=true; for(int i=h[pos];i!=-1;i=ne[i]){ if(dist[e[i]]>dist[pos]+w[i]){ dist[e[i]]=dist[pos]+w[i]; q.push({dist[e[i]],e[i]}); } } } for(int i=0;i<4;i++){ res=min(res,dist[End+i]); } } int main(){ memset(h,-1,sizeof(h)); int cnt=0,s; cin>>n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>room[i][j]; if(room[i][j]=='A')s=cnt; if(room[i][j]=='B')End=cnt; if(room[i][j]=='x')continue; mp[{i,j}]=cnt; cnt+=4; } } if(n==1){cout<<0<<endl; return 0;} for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(room[i][j]=='x')continue; for(int k=0;k<4;k++){ int x1=i+dir[k][0],y1=j+dir[k][1]; if(x1>n||x1<=0||y1>n||y1<=0||room[x1][y1]=='x')continue; int d1=mp[{i,j}],d2=mp[{x1,y1}]; for(int z=0;z<4;z++){ int xx=d1+z,yy=d2+k; if(z==k)add(xx,yy,0),add(yy,xx,0); else add(xx,yy,1),add(yy,xx,1); } } } } for(int i=0;i<=3;i++){ int ss=s+i; Dijkstra(ss); } cout<<res<<endl; }