codeforces 1046I. Say Hell

题目连接

题意:两个人沿着直线行走,如果他们之间距离小于d1,就会打招呼,在打完招呼后的某个时间点(共N个时间点),他们两人之间的距离>d2,那么下一次他们之间距离再次小于d1时会再打招呼。

题解:可以将两条线段之间的最短距离转化为点与线段的最短距离,然后就是改一下大白上点到线段上距离的模版即可。

​
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int MX = 1e5+7;
LL d1,d2;
struct Point {
    LL x, y;
    Point() {}
    Point(LL x,LL y):x(x),y(y) {}
}P[MX],Q[MX];
typedef Point Vector;
Vector operator-(Vector A,Vector B) {return Vector(A.x - B.x, A.y - B.y);}
Vector operator+(Vector A,Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator*(Vector A,LL p) {return Vector(A.x*p, A.y*p);}
bool operator==(Point A, Point B) {return (A.x==B.x && A.y == B.y); }
LL Dot(Vector A,Vector B) { //点积
    return A.x*B.x+A.y*B.y;//如果改成整形记得加LL
}
LL Cross(Vector A,Vector B) { //叉积
    return A.x*B.y-A.y*B.x;//如果改成整形记得加LL
}
//向量长度
LL Length(Vector A) {
    return sqrt(Dot(A,A));
}
LL Length2(Vector A){
    return Dot(A,A);
}

bool check(int i,Point P, Point A, Point B)
{
    if(A == B) return Length2(P-A) <= d1*d1;
    Vector v1 = B-A, v2 = P-A, v3 = P-B;
    if(Dot(v1,v2) < 0) return Length2(v2) <= d1*d1;
    else if(Dot(v1,v3) > 0) return Length2(v3) <= d1*d1;
    else return Cross(v1,v2)*Cross(v1,v2) <= Length2(v1)*d1*d1;
}

int main()
{
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif // LOCAL
    int n;
    scanf("%d%I64d%I64d",&n,&d1,&d2);
    for(int i = 0; i < n; i++){
        scanf("%I64d %I64d %I64d %I64d",&P[i].x,&P[i].y,&Q[i].x,&Q[i].y);
    }
    bool flag = 0;
    int ans = 0;
    if(Length2(P[0]-Q[0]) <= d1*d1){
        ++ans;
        flag = 1;
    }
    for(int i = 1; i < n; i++){
        bool f = check(i,P[i-1],Q[i-1],Q[i-1] + (Q[i]-Q[i-1]) - (P[i]-P[i-1]) );
        if(!flag && f) ++ans;
        flag |= f;
        if(Length2(P[i]-Q[i]) > d2*d2) flag = 0;
    }
    cout<<ans<<endl;
}
​

猜你喜欢

转载自blog.csdn.net/qq_18869763/article/details/82829343