2019百度之星 C Mindis —— 离散区间 + BFS

题目链接:点我啊╭(╯^╰)╮

题目大意:

    中文题

解题思路:

    将整个图离散化一下,注意:
    由于一个矩形是一个区间,我们要考虑的是区间内的速度
    所以离散化时不能左闭右开,而是计算速度的时候左闭右开
    计算速度有四个方向的速度,这里只用了两个方向
    BFS的过程中特判一下速度的方向即可

核心:离散区间后跑最短路

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <ll,int>;
const int maxn = 2e3 + 5;
const double eps = 1e-7;
int tx[5] = {1,-1,0,0};
int ty[5] = {0,0,1,-1};
int T, n, xa, ya, xb, yb, sx, sy;
int spe1[maxn][maxn], spe2[maxn][maxn];
double ans, Time[maxn][maxn];
vector <int> lsx, lsy;
struct Node{
	int x1, y1, x2, y2; 
} a[maxn];
struct node{
	int x, y; 
	double ti;
	bool operator <(const node &A)const{
		return ti > A.ti;
	}
} ;
priority_queue <node> Q;

int getidx(int x){
	return lower_bound(lsx.begin(), lsx.end(), x) - lsx.begin();
}
int getidy(int x){
	return lower_bound(lsy.begin(), lsy.end(), x) - lsy.begin();
}

void bfs(int stx, int sty){
	while(!Q.empty()) Q.pop();
	node q, tmp;
	q.x = stx, q.y = sty, q.ti = 0;
	Q.push(q);
	Time[q.x][q.y] = 0;
	while(!Q.empty()){
		q = Q.top();
		Q.pop();
		if(fabs(q.ti-Time[q.x][q.y]) > eps) continue;
		if(q.x==xb && q.y==yb) {
			ans = q.ti;
			return;
		}
		for(int i=0; i<4; i++){
			int nx = q.x + tx[i];
			int ny = q.y + ty[i];
			if(nx<0 || ny<0 || nx>=sx || ny>=sy) continue;
			double speed1, speed2, new_ti;
			
			int disx = abs(lsx[nx] - lsx[q.x]);
			int disy = abs(lsy[ny] - lsy[q.y]);
			if(tx[i] == 0) {
				if(ty[i]>0) speed2 = spe2[q.x][q.y];
				else speed2 = spe2[nx][ny];
				new_ti = disy / speed2 + q.ti;
			}
			if(ty[i] == 0) {
				if(tx[i]>0) speed1 = spe1[q.x][q.y];
				else speed1 = spe1[nx][ny];
				new_ti = disx / speed1 + q.ti;
			}
			if(new_ti >= Time[nx][ny]) continue;
			Time[nx][ny] = new_ti;
			tmp.x = nx, tmp.y = ny, tmp.ti = new_ti;
			Q.push(tmp);
		}
	}
}

int main() {
	scanf("%d", &T);
	while(T--){
		ans = 0;
		scanf("%d", &n);
		memset(spe1, 0, sizeof(spe1));
		memset(spe2, 0, sizeof(spe2));
		lsx.clear(), lsy.clear();
		for(int i=1; i<=n; i++){
			scanf("%d%d", &a[i].x1, &a[i].y1);
			scanf("%d%d", &a[i].x2, &a[i].y2);
			lsx.push_back(a[i].x1), lsx.push_back(a[i].x2);
			lsy.push_back(a[i].y1), lsy.push_back(a[i].y2);
		}
		
		scanf("%d%d%d%d", &xa, &ya, &xb, &yb);
		lsx.push_back(xa), lsx.push_back(xb);
		lsy.push_back(ya), lsy.push_back(yb);
		sort(lsx.begin(),lsx.end());
		sort(lsy.begin(),lsy.end());
		lsx.erase(unique(lsx.begin(), lsx.end()), lsx.end());
		lsy.erase(unique(lsy.begin(), lsy.end()), lsy.end());
		sx = lsx.size(), sy = lsy.size();
		
		for(int i=0; i<lsx.size(); i++)
			for(int j=0; j<lsy.size(); j++)
				spe1[i][j]++, spe2[i][j]++, Time[i][j] = 1e15;
		for(int i=1; i<=n; i++){
			int x1 = getidx(a[i].x1), x2 = getidx(a[i].x2);
			int y1 = getidy(a[i].y1), y2 = getidy(a[i].y2);
			for(int xi=x1; xi<=x2-1; xi++)
				for(int xj=y1; xj<=y2; xj++)
					spe1[xi][xj]++;
					
			for(int xi=x1; xi<=x2; xi++)
				for(int xj=y1; xj<=y2-1; xj++)
					spe2[xi][xj]++;
		}
		xa = getidx(xa), ya = getidy(ya);
		xb = getidx(xb), yb = getidy(yb);
		bfs(xa, ya);
		printf("%.5f\n", ans);
	}
}
/*
100
2
0 1 2 2
1 1 3 2
0 0 3 3
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值