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((2∗k+2)3) +
(
2
∗
k
+
2
)
(2*k+2)
(2∗k+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;
}