[CF 242C][BNUOJ 26638] King's Path [最短路]

23 篇文章 0 订阅
17 篇文章 0 订阅

在一个很大的平面上(10^9*10^9),所有的点均为整点,有一些点是可以访问的,有一些点是不能访问的,可以访问的点用一些线段表示,r,x,y表示(r,x),(r,x+1),...,(r,y)均是可访问的。现在已知King在一个可以访问的点上,他想去另一个可以访问的点,他每一步只可以走到相邻八个格中的某个可以访问的点,问他所需要走的最短路程的长度。已知起点和终点不会是同一个点。若无法到达则输出-1。

数据范围:所有线段的长度和不会超过10^5

因为数据范围很小,所以直接利用map记录所有的线段上的点,然后挨个点判断它周围八个点是否是可以访问的点(是否也是线段上的点),若可以访问则建立一条边权为1的边,然后从起点到终点bfs一遍求出最短路即可。

#include <cstdio>
#include <map>
#include <utility>
#include <cstring>

using namespace std;

const int dir[8][2]={{-1,-1},{1,1},{-1,1},{1,-1},{0,-1},{-1,0},{1,0},{0,1}};

struct Node {
	int fe,v;
};
struct Edge {
	int t,ne;
};

map<pair<int,int>,int> c;
Node a[100100];
int que[100100];
Edge b[800100];
int n,p;

void putedge(int x,int y) {
	b[p].t=y;
	b[p].ne=a[x].fe;
	a[x].fe=p++;
}

void bfs(int s,int t) {
	int p=0,q=0,i,j;
	que[q++]=s;
	a[s].v=0;
	while (p!=q) {
		i=que[p++];
		for (j=a[i].fe;j!=-1;j=b[j].ne) {
			if (a[b[j].t].v==-1) {
				a[b[j].t].v=a[i].v+1;
				que[q++]=b[j].t;
			}
		}
	}
}

int main() {
	int nn,i,x,y,z,j;
	int x0,y0,x1,y1;
	n=1;
	memset(a,-1,sizeof(a));
	p=0;
	scanf("%d%d%d%d",&x0,&y0,&x1,&y1);
	c[make_pair(x0,y0)]=n++;
	c[make_pair(x1,y1)]=n++;
	scanf("%d",&nn);
	for (i=0;i<nn;i++) {
		scanf("%d%d%d",&x,&y,&z);
		for (j=y;j<=z;j++) {
			if (c[make_pair(x,j)]==0) c[make_pair(x,j)]=n++;
		}
	}
	for (map<pair<int,int>,int>::iterator it=c.begin();it!=c.end();it++) {
		i=it->second;x=it->first.first;y=it->first.second;
		//printf("%d,%d : %d\n",x,y,i);
		for (j=0;j<8;j++) {
			map<pair<int,int>,int>::iterator it2=c.find(make_pair(x+dir[j][0],y+dir[j][1]));
			if (it2!=c.end()) putedge(i,it2->second);
		}
	}
	bfs(1,2);
	printf("%d\n",a[2].v);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值