每日水题(002-1)(最短路)P2083 找人

一、算法分析

本来是打算找一道搜索题做的,然后找到了这个题,结果仔细一看,多起点,单终点,正着走反着走完全等效,然后直接套上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;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值