一、算法分析
本来是打算找一道搜索题做的,然后找到了这个题,结果仔细一看,多起点,单终点,正着走反着走完全等效,然后直接套上dijkstra板子就过了(虽然用时是BFS的十倍)。基本思路是把要找的人看做起点,还有就是细节处理方面,每个房间有两个位置参数,即层数与房间号,这两个数可以直接压成一个数用来表示房间(见代码)。
二、代码及注释
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int maxn=1000005;
const int inf=0x3f3f3f3f;
int d[maxn];
bool done[maxn];
int n,m,v,x,y;
struct edge{
int from;
int to;
int dist;
edge(int u,int v,int d):from(u),to(v),dist(d){}
edge():from(0),to(0),dist(0){}
};
vector<edge> edges;
vector<int> mp[maxn];
void addedge(int from,int to,int dist){
edges.push_back(edge(from,to,dist));
int len=edges.size();
mp[from].push_back(len-1);
}
struct heapnode{
int num;
int dis;
heapnode(int u,int v):num(u),dis(v){}
heapnode():num(0),dis(0){}
bool operator < (const heapnode& buf) const {
return dis>buf.dis;
}
};
priority_queue<heapnode> q;
void dijkstra(int s){
for(int i=1;i<=n*m;i++) d[i]=inf; //把二维压到一维之后,一维数据会增多,所以记得修改这里,应该是n*m
memset(done,0,sizeof(done));
d[s]=0;
q.push(heapnode(s,0));
while(!q.empty()){
heapnode top=q.top();
q.pop();
if(done[top.num]) continue;
done[top.num]=true;
for(int i=0;i<mp[top.num].size();i++){
edge& e=edges[mp[top.num][i]];
if(d[top.num]+e.dist<d[e.to]){
d[e.to]=d[top.num]+e.dist;
q.push(heapnode(e.to,d[e.to]));
}
}
}
}
int pos;
int ans=inf;
int main(){
int uu,vv;
scanf("%d%d%d%d%d",&n,&m,&v,&x,&y);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d%d",&uu,&vv);
if(uu==i && vv==j) continue; //把二维压成一维存
addedge((uu-1)*m+vv,(i-1)*m+j,abs(uu-i)*v);//考虑同学找小明,这样把题目中的关系反向建图
//printf("%d %d %d\n",(uu-1)*m+vv,(i-1)*m+j,abs(uu-i)*v);
}
dijkstra((x-1)*m+y);
for(int i=1;i<=m;i++){
ans=min(ans,d[i]); //找第一层中距离最近的
}
if(ans!=inf) printf("%d",ans);
else printf("impossible");
return 0;
}