2020ICPC·小米 网络选拔赛第一场 B. Intelligent Robot (计算几何+最短路)

Description
在这里插入图片描述
Input
6 3 2
1 1 3 1
2 2 5 2
3 0 3 3

Output
3.8284

Solution
容易发现只有2*k+2个点可能做为路径上的拐点,在这些点上跑最短路即可
建图时需要判断路径的合法性(即不会经过任意一堵墙)
复杂度 = 建图复杂度 O ( ( 2 ∗ k + 2 ) 3 ) O((2*k+2)^3) O((2k+2)3) + ( 2 ∗ k + 2 ) (2*k+2) (2k+2)个点dijkstra复杂度

Code

#include <bits/stdc++.h>
//pair
#define pii pair<int,int>
#define mpp make_pair
#define fi first
#define se second
// //debug
#define debug1(x) cout << "[" << #x << " = " << (x) << "]\n"
#define debug2(x,y) cout << "[" << #x << " = " << (x) << "  " << #y << " = " << (y) << "]\n"
#define debug3(x,y,z) cout << "[" << #x << " = " << (x) << "  " << #y << " = " << (y) << "  " << #z << " = " << (z) << "]\n"
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 600 + 7;
int n,m,k;
struct Point{
	int x,y;
}p[maxn];
pair<Point,Point>seg[maxn];
inline double d(Point i,Point j) {
	int x1 = i.x, x2 = j.x;
	int y1 = i.y, y2 = j.y;
	return sqrt(1.0*(x1-x2)*(x1-x2)+1.0*(y1-y2)*(y1-y2));
}
inline int mul(Point i,Point j) {
	int x1 = i.x, x2 = j.x;
	int y1 = i.y, y2 = j.y;
	return x1 * y2 - x2 * y1;
}
bool flg(int x,int y) {
	if((x<0&&y>0)||(x>0&&y<0)) return true;
	return false;
}
int ecnt,head[maxn];
struct Edge{
	int v;double w;int next;
}e[maxn*maxn];
inline void add(int u,int v,double w){
	e[++ecnt] = (Edge) {v,w,head[u]}, head[u] = ecnt;
	e[++ecnt] = (Edge) {u,w,head[v]}, head[v] = ecnt;
}
Point vec(Point i, Point j) {
	return (Point){j.x-i.x,j.y-i.y};
}
int num;
void build() {
	for(int i = 0;i <= num;++i) {
		for(int j = i+1;j <= num;++j) {
			Point tmp1 = vec(p[i],p[j]);
			int cnt = 0;
			for(int x = 1;x <= k;++x) {
				Point tmp2 = vec(seg[x].fi,seg[x].se);
				int f1 = flg(mul(tmp1,vec(p[i],seg[x].fi)), mul(tmp1,vec(p[i],seg[x].se)));
				int f2 = flg(mul(tmp2,vec(seg[x].fi,p[i])), mul(tmp2,vec(seg[x].fi,p[j])));
				// debug2(i,j);
				// debug2(f1,f2);
				if(f1&&f2) cnt++;
			}
			//debug3(i,j,cnt);
			if(cnt==0) add(i,j,d(p[i],p[j]));
		}
	}
}
struct node{
	int now;double w;
	inline bool operator<(const node&it)const{
		return w>it.w;
	}
};
double dis[maxn];
bool vis[maxn];
double dijkstra() {
	int s = 0, t = num;
	priority_queue<node>q;
	for(int i = 0;i <= num;++i) {
		vis[i] = false; dis[i] = LINF;
	}dis[s] = 0.0;q.push((node){s,0.0});
	while(!q.empty()) {
		node tmp = q.top();q.pop();
		int u = tmp.now;if(vis[u]) continue;vis[u] = true;
		for(int i = head[u];i;i=e[i].next) {
			int v = e[i].v;double w = e[i].w;
			if(dis[v] >= dis[u] + w) {dis[v] = dis[u] + w;q.push((node){v,dis[v]});}
		}
	}return dis[t];
}
int main() {
	scanf("%d %d %d",&n,&m,&k);
	num = k + k + 1;
	for(int i = 1;i <= k;++i) {
		scanf("%d %d %d %d",&p[i].x,&p[i].y,&p[i+k].x,&p[i+k].y);
		seg[i] = {p[i], p[i+k]};
	}scanf("%d %d %d %d",&p[0].x,&p[0].y,&p[num].x,&p[num].y);
	build();double res = dijkstra();printf("%.4f\n", res);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值