[TC6194]AllWoundUp

[TC6194]AllWoundUp

题目大意:

\(A\)\(B\)两个人。\(A\)在平面上游走,\(B\)会一直盯着\(A\)看,站在\(x\)轴某个位置上不动,并随着\(A\)的运动旋转身体。\(A\)的移动轨迹是一个闭合折线,包含\(n(n\le1000)\)条线段。试最大化\(B\)逆时针旋转的次数。

思路:

\(A\)的移动轨迹将\(x\)轴分成若干段。对于同一段上的点,无论\(B\)站在哪个位置效果都是一样的。枚举\(B\)所在的位置,枚举\(A\)移动路径上的每一条边,计算\(A\)\(B\)旋转的角度即可。

源代码:

#include<cmath>
#include<vector>
#include<algorithm>
#define double long double
class AllWoundUp {
    private:
        static const int N=1000;
        struct Point {
            double x,y;
            double operator * (const Point &rhs) const {
                return x*rhs.y-y*rhs.x;
            }
            Point operator - (const Point &rhs) const {
                return (Point){x-rhs.x,y-rhs.y};
            }
            double operator ^ (const Point &rhs) const {
                return x*rhs.x+y*rhs.y;
            }
        };
        Point p[N];
        double c[N];
        int n,m;
        bool in(const double &x,const double &x1,const double &x2) const {
            return std::min(x1,x2)<=x&&x<=std::max(x1,x2);
        }
        double calc(const Point &a,const Point &b) const {
            return atan2(a*b,a^b);
        }
        int solve(const double &x0) const {
            double angle=0;
            const Point c=(Point){x0,0};
            for(register int i=0;i<n;i++) {
                const int j=(i+1)%n;
                if(p[i].y==0&&p[j].y==0&&in(x0,p[i].x,p[j].x)) return 0;
                angle+=calc(p[i]-c,p[j]-c);
            }
            return angle/M_PI/2;
        }
    public:
        int maxWind(const std::vector<int> &v1,const std::vector<int> &v2) {
            n=v1.size();
            for(register int i=0;i<n;i++) p[i].x=v1[i];
            for(register int i=0;i<n;i++) p[i].y=v2[i];
            for(register int i=0;i<n;i++) {
                const int j=(i+1)%n;
                if(p[i].y*p[j].y>0||p[i].y==p[j].y) continue;
                if(p[i].x!=p[j].x) {
                    const double k=(p[i].y-p[j].y)/(p[i].x-p[j].x);
                    const double b=p[i].y-k*p[i].x;
                    c[m++]=-b/k;
                } else {
                    c[m++]=p[i].x;
                }
            }
            if(m==0) return 0;
            std::sort(&c[0],&c[m]);
            m=std::unique(&c[0],&c[m])-c;
            int ans=0;
            for(register int i=1;i<m;i++) {
                ans=std::max(ans,solve((c[i-1]+c[i])/2));
            }
            return ans;
        }
};

猜你喜欢

转载自www.cnblogs.com/skylee03/p/9373593.html
tc