题意:
给了一个n * m的矩阵,让从起点走到终点的最小花费是多少。
有一些地点可以进行传送,不过需要花费的时间为3,其他的正常上下左右走花费的时间是1。
思路:
挺简单的题。
就是找到起点的位置,对于当前队列头的点,去走四个方向是不是满足要求。
然后再看当前点是不是有传送门,看传送的地点是不是满足即可。
因为要求花费时间最优,边权不都是1,所以用优先队列去bfs即可
第一次到达终点的花费就是最小花费。
对于标记有一个细节
就是如果新的点是通过上下左右直接走到的,肯定可以标记掉,因为是附近的。
但如果是传送门过去的就不要标记,因为传送门过去的不一定最优。
比如从(x,y) 传送到(x,y+2) 传送门要花费3,如果标记掉了,那么就错了 因为直接走过去只需要花费2
当然了这个还是看个人写法。可以直接把满足的都丢尽队列内,第一次取到这个坐标的时候的标记掉这个位置,后面如果在取到这个左边就continue,这样方便点。
偷个懒,优先队列没用结构体存,直接优先队列套两个pair了
#include<bits/stdc++.h>
using namespace std;
char mp[305][305];
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
map<pair<int,int>,vector<pair<int,int>>> k;
bool vis[305][305];
int n,m,q;
bool check(int x,int y){
if(x<0 || x>=n || y<0 || y>=m || vis[x][y] || mp[x][y]=='#') return 1;
return 0;
}
void bfs(){
int ex,ey;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='S'){
ex=i;ey=j;break;
}
}
}
priority_queue<pair<int,pair<int,int>>> q;
q.push({0,{ex,ey}});
vis[ex][ey]=1;
while(!q.empty()){
pair<int,pair<int,int>> now=q.top();
int num=now.first;
int x=now.second.first,y=now.second.second;
if(mp[x][y]=='T'){
cout<<-num<<endl;
return ;
}
q.pop();
for(int i=0;i<4;i++){
int fx=x+dx[i],fy=y+dy[i];
if(check(fx,fy)) continue;
vis[fx][fy]=1;
q.push({num-1,{fx,fy}});
}
for(auto it:k[{x,y}]){
int fx=it.first,fy=it.second;
if(check(fx,fy)) continue;
q.push({num-3,{fx,fy}});
}
}
cout<<-1<<endl;
}
int main(){
while(cin>>n>>m>>q){
for(int i=0;i<n;i++) cin>>mp[i];
k.clear();
memset(vis,0,sizeof vis);
while(q--){
int a,b,c,d;cin>>a>>b>>c>>d;
k[{a,b}].push_back({c,d});
}
bfs();
}
return 0;
}

京公网安备 11010502036488号