Intelligent Robot
链接:https://ac.nowcoder.com/acm/contest/7501/B
思路:
只考虑特殊点即墙的端点,起点和终点。对于每个点都与另外的所有点尝试建边,建边的条件是这个边不会穿过墙。那么最后跑个最短路即可。
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 610;
int head[maxn], tot;
double d[maxn];
bool vis[maxn];
struct Point
{
double x,y;
Point(){}
//定义运算
Point(double _x,double _y){x = _x;y = _y;}
Point operator + (const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator - (const Point &b)const{
return Point(x-b.x,y-b.y);
}
Point operator * (const double &k)const{//乘常数
return Point(x*k,y*k);
}
Point operator / (const double &k)const{
return Point(x/k,y/k);
}
//点的叉积和点积都是数
//点积
double operator * (const Point &b)const{
return x*b.x+y*b.y;
}
//叉积
double operator ^ (const Point &b)const{
return x*b.y-y*b.x;
}
double powlen(){return x*x+y*y;};
double len(){return sqrt(powlen());}
}sta, ed;
inline double dis(Point p1,Point p2) {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
struct Line{
Point a, b;
Line(){}
Line(Point p1, Point p2) {
this -> a = p1;
this -> b = p2;
}
double Len() {
return dis(a, b);
}
}a[maxn];
struct Node{
int u, v, nxt;
double w;
}e[maxn * maxn];
struct A{
int pos;
double cost;
bool operator < (const A &a1)const{
return cost > a1.cost;
}
};
int n, m, k;
bool judge(Line line) {
for(int i = 1; i <= k; i++) {
Point AB = line.b - line.a;
Point AC = a[i].a - line.a;
Point AD = a[i].b - line.a;
Point CD = a[i].b - a[i].a;
Point CB = line.b - a[i].a;
Point CA = line.a - a[i].a;
if((AB^AC)*(AB^AD) < 0 && (CD^CB)*(CD^CA) < 0) return true;
}
return false;
}
inline void add(int x, int y, double z)
{
e[++tot].u = x;
e[tot].v = y;
e[tot].w = z;
e[tot].nxt = head[x];
head[x] = tot;
}
void dij(int src)
{
for(int i = 0; i < 610; i++) d[i] = 1e18;
memset(vis, 0, sizeof(vis));
priority_queue<A>q;
d[src] = 0;
A now;
now.cost = 0;
now.pos = src;
q.push(now);
while(!q.empty())
{
now = q.top();
q.pop();
if(vis[now.pos])
continue;
vis[now.pos] = 1;
for(int i = head[now.pos]; ~i; i = e[i].nxt)
{
int to = e[i].v;
if(!vis[to] && d[to] > e[i].w + d[e[i].u])
{
d[to] = d[e[i].u] + e[i].w;
now.cost = d[to];
now.pos = to;
q.push(now);
}
}
}
}
int main()
{
memset(head, -1, sizeof(head));
vector<Point> vec;
scanf("%d%d%d",&n,&m,&k);
for(int i = 1; i <= k; i++){
Point p1, p2;
scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y);
a[i].a = p1; a[i].b = p2;
}
scanf("%lf%lf%lf%lf",&sta.x,&sta.y,&ed.x,&ed.y);
vec.push_back(sta);
for(int i = 1; i <= k; i++) {
vec.push_back(a[i].a);
vec.push_back(a[i].b);
}
vec.push_back(ed);
int sz = vec.size();
for(int i = 0; i < sz; i++) {
for(int j = i+1; j < sz; j++) {
Line line = Line(vec[i], vec[j]);
if(!judge(line)) {
double len = dis(vec[i], vec[j]);
// cout << i << " " << j << " " <<len << endl;
add(i, j, len);
add(j, i, len);
}
}
}
dij(0);
printf("%.4f\n",d[vec.size()-1]);
return 0;
}
