-----------------------前面的两场感觉质量不高,就没写题解-----------------------------

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;
}
View Code

相关文章:

  • 2021-10-24
  • 2022-12-23
  • 2021-08-18
  • 2021-05-27
  • 2021-11-26
  • 2021-06-19
  • 2021-10-07
  • 2022-01-28
猜你喜欢
  • 2021-08-14
  • 2021-10-16
  • 2021-09-10
  • 2021-10-26
  • 2022-12-23
  • 2021-10-26
  • 2021-11-15
相关资源
相似解决方案