-----------------------前面的两场感觉质量不高,就没写题解-----------------------------
A .Around the Track
pro:给定内多边形A和外多边形B,求最短路径,蛮子路径再A之外,B之内。
sol:如果没有B,就是求凸包,有了B,我们在做凸包的时候,有形如“a-b-c,b在内部,删去b,连接a-c的操作”,如果a-c和B不相交,直接删去b,否则用B的凸包代替b处。
#include <bits/stdc++.h> using namespace std; #define x first #define y second typedef pair<int, int> Point; typedef long long LL; const int maxn=110; bool operator != (Point b, Point c) { return (b.x!=c.x || b.y!=c.y); } double dis(Point b, Point c); struct polygon { int n; bool cannotdel[maxn]; Point p[maxn]; polygon():n(0){} void read() { scanf("%d", &n); for (int i=1; i<=n; ++i) scanf("%d%d", &p[i].x, &p[i].y); p[0]=p[n]; p[n+1]=p[1]; for (int i=1; i<=n; ++i) cannotdel[i]=false; } double track() { double ans=0; for (int i=1; i<=n; ++i) ans+=dis(p[i], p[i+1]); return ans; } void del(int pos) { for (int i=pos; i<n; ++i) { p[i]=p[i+1]; cannotdel[i]=cannotdel[i+1]; } --n; p[n+1]=p[1]; p[0]=p[n]; } void insert(int posl, int posr, vector<Point> &newp) { int m=posl+n-posr+1+newp.size(); for (int i=0; i<(n-posr+1); ++i) { p[m-i]=p[n-i]; cannotdel[m-i]=cannotdel[n-i]; } n=m; m=newp.size(); for (int i=0; i<m; ++i) { p[posl+1+i]=newp[i]; cannotdel[posl+1+i]=true; } p[n+1]=p[1]; p[0]=p[n]; } void print() { puts("======================"); for (int i=1; i<=n+1; ++i) printf("%d %d\n", p[i].x, p[i].y); } }; polygon inner, outer; Point pp[maxn]; Point globalps; set<Point> innerpoint; vector<Point> newp; inline LL sqr(LL x) { return x*x; } LL det(Point b, Point c, Point o) { return (b.x-o.x)*(c.y-o.y)-(b.y-o.y)*(c.x-o.x); } double dis(Point b, Point c) { return sqrt(sqr(b.x-c.x)+sqr(b.y-c.y)); } LL sdis(Point b, Point c) { return (sqr(b.x-c.x)+sqr(b.y-c.y)); } bool intriangle(Point &b, Point &c, Point &d, Point &o) { return (abs(det(b, c, o))+abs(det(b, d, o))+abs(det(c, d, o)))==abs(det(b, c, d)); } bool cmp(Point b, Point c) { LL tmp=det(b, c, globalps); if (tmp!=0) return tmp<0; return sdis(b, globalps)<sdis(c, globalps); } void convex(vector<Point> &p, Point &ps, Point &pf) { globalps=ps; sort(p.begin(), p.end(), cmp); int n=p.size(); for (int i=1; i<=n; ++i) pp[i]=p[i-1]; pp[++n]=pf; pp[0]=ps; int m=0; for (int i=1; i<=n; ++i) { while (m>0 && det(pp[i], pp[m], pp[m-1])<0) --m; pp[++m]=pp[i]; } p.resize(m-1); for (int i=1; i<m; ++i) p[i-1]=pp[i]; } void solve() { for (int i=1; i<=inner.n; ++i) innerpoint.insert(inner.p[i]); while (1) { bool flag=false; for (int i=1; i<=inner.n; ++i) if (!inner.cannotdel[i] && det(inner.p[i+1], inner.p[i-1], inner.p[i])<0) { newp.clear(); for (int j=1; j<=outer.n; ++j) if (intriangle(inner.p[i-1], inner.p[i], inner.p[i+1], outer.p[j])) if (innerpoint.count(outer.p[j])==0) newp.push_back(outer.p[j]); for (int j=1; j<=inner.n; ++j) if (inner.p[j]!=inner.p[i-1] && inner.p[j]!=inner.p[i] && inner.p[j]!=inner.p[i+1] && intriangle(inner.p[i-1], inner.p[i], inner.p[i+1], inner.p[j])) newp.push_back(inner.p[j]); if (newp.size()==0) { flag=true; inner.del(i); break; } convex(newp, inner.p[i-1], inner.p[i+1]); flag=true; for (auto &p:newp) if (innerpoint.count(p)) { flag=false; break; } if (!flag) continue; for (auto &p:newp) innerpoint.insert(p); inner.insert(i-1, i+1, newp); } if (!flag) break; } printf("%.7lf\n", inner.track()); } int main() { inner.read(); outer.read(); solve(); return 0; }