题目背景:
贝茜遇到了一件很麻烦的事:她无意中闯入了森林里的一座城堡,如果她想回家,就必须穿过这片由骑士们守护着的森林.为了能安全地离开,贝茜不得不按照骑士们的要求,在森林寻找一种特殊的灌木并带一棵给他们.当然,贝茜想早点离开这可怕的森林,于是她必须尽快完成骑士们给的任务,贝茜随身带着这片森林的地图,地图上的森林被放入了直角坐标系,并按x,y轴上的单位长度划分成了W×H(1≤W,H≤1000)块,贝茜在地图上查出了她自己以及骑士们所在的位置,当然地图上也标注了她所需要的灌木生长的区域.某些区域是不能通过的(比如说沼泽地,悬崖,以及食人兔的聚居地).在没有找到灌木之前,贝茜不能通过骑士们所在的那个区域,为了确保她自己不会迷路,贝茜只向正北、正东、正南、正西四个方向移动(注意,她不会走对角线).她要走整整一天,才能从某块区域走到与它相邻的那块区域. 输入数据保证贝茜一定能完成骑士的任务.贝茜希望你能帮她计算一下,她最少需要多少天才可脱离这可怕的地方?
题目大意:
一个w*h的矩阵,有不能到达的点,从起点经过多个中间点其中的一个然后到达终点的最短路
注意事项:
只有一个起点和一个终点,也就是说"骑士们"其实只有一个
题解:
我看其他的博客有用两遍dfs然后遍历所有点相加的。。。
然而当时我都写完代码了,正在调,感觉那个方法好机智啊qwq
我是正常跑spfa,然后维护最短路的数组开两维,一个是捡到灌木之前的,一个是之后的
具体看代码吧
#include<iostream>
#include<cstdio>
#include<queue>
#define inf 10000000
using namespace std;
struct point{
int x,y;
friend bool operator == (point a,point b){
if(a.x==b.x && a.y==b.y)return true;
else return false;
}
};
struct node{
bool guan;
point now;
int num;
friend bool operator < (node a,node b){
return a.num>b.num;
}
};
int tox[4]={-1,0,1,0};
int toy[4]={0,1,0,-1};
point s,t;
int n,m;
int a[1010][1010];
int Min[1010][1010][2];
priority_queue<node>q;
int main(){
scanf("%d%d",&m,&n);
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
scanf("%d",&a[i][j]);
if(a[i][j]==2)s.x=i,s.y=j;
if(a[i][j]==3)t.x=i,t.y=j;
Min[i][j][0]=Min[i][j][1]=inf;
}
}
node tt;
tt.guan=false;
tt.now=s;
Min[s.x][s.y][0]=0;
tt.num=0;
q.push(tt);
while(!q.empty()){
tt=q.top();
q.pop();
if(tt.guan && tt.now==t){
break;
}
for(int i=0; i<4; i++){
node t1=tt;
t1.now.x+=tox[i];
t1.now.y+=toy[i];
if(t1.now.x<1 || t1.now.x>n || t1.now.y<1 || t1.now.y>m)continue;
if(a[t1.now.x][t1.now.y]==1)continue;
if(Min[t1.now.x][t1.now.y][t1.guan]<=t1.num+1)continue;
Min[t1.now.x][t1.now.y][t1.guan]=t1.num+1;
if(t1.guan==false && a[t1.now.x][t1.now.y]==4){
t1.guan=true;
Min[t1.now.x][t1.now.y][t1.guan]=Min[t1.now.x][t1.now.y][0];
}
t1.num++;
q.push(t1);
}
}
printf("%d\n",tt.num);
return 0;
}