zoukankan      html  css  js  c++  java
  • 2020ICPC昆明站——J.Mr. Main and Windmills(计算几何)

    原题链接
    题意:
    车从 ( s x , s y ) (sx,sy) (sx,sy)开往 ( e x , e y ) (ex,ey) (ex,ey),在车的同一侧有 n n n个风车, q q q次询问,每次询问第 h h h个点对于其他点的位置变化的第 k k k次的点。
    思路:
    题意有点抽象,模拟一下样例就很好懂了。
    在这里插入图片描述

    第二个样例问的是3号点第二个变化的位置点。
    s s s e e e走,当车在 [ s , A ] [s,A] [s,A]区间时,在车的视角看, 1 , 2 , 4 1,2,4 1,2,4都在 3 3 3的左边。
    当车在 [ A , B ] [A,B] [A,B]区间时, 4 4 4变成了在 3 3 3的右边,而 1 , 2 1,2 1,2都在 3 3 3的左边,所以第一个变化的点是 4 4 4,第一个变化的位置是 A A A.
    当车在 [ B , C ] [B,C] [B,C]区间时, 2 2 2也变成了在 3 3 3的右边,这时候 2 , 4 2,4 2,4都在 3 3 3的右边, 1 1 1 3 3 3的左边,所以第二个变化的点是 2 2 2,第二个变化的位置是 B B B.
    当车在 [ C , + 00 ] [C,+00] [C,+00]区间时, 1 1 1也变成了在 3 3 3的右边,这时候 1 , 2 , 4 1,2,4 1,2,4都在 3 3 3的右边,所以第三个变化的点是 1 1 1,第二个变化的位置是 C C C.
    思路就是求每个点跟询问点所组成的直线和直线 ( s , e ) (s,e) (s,e)的交点,按照交点到起点 s s s的距离从小到大排序,第k个的交点坐标就是答案。
    要注意只有交点在 [ s , e ] [s,e] [s,e]时才是有效的。
    运气比较好,找的板子没有被卡精度。
    代码:

    #pragma GCC optimize(2)
    
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll, ll>PLL;
    typedef pair<int, int>PII;
    typedef pair<double, double>PDD;
    #define I_int ll
    inline ll read()
    {
        ll x = 0, f = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-')f = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    #define read read()
    #define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    #define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i<(b);i++)
    #define per(i,a,b) for(int i=(a);i>=(b);i--)
    #define perr(i,a,b) for(int i=(a);i>(b);i--)
    ll ksm(ll a, ll b, ll p)
    {
        ll res = 1;
        while(b)
        {
            if(b & 1)res = res * a % p;
            a = a * a % p;
            b >>= 1;
        }
        return res;
    }
    const int inf = 0x3f3f3f3f;
    #define PI acos(-1)
    const double eps = 1e-8;
    const int maxn=1e6+100;
    int n,m;
    const double epsi=1e-10;
    struct Point
    {
    	double x,y;
    	Point(double _x=0,double _y=0):x(_x),y(_y){}
    	Point operator -(const Point &op) const
    	{
    		return Point(x-op.x,y-op.y);
    	}
    	double operator ^(const Point &op) const
    	{
    		return x*op.y-y*op.x;
    	}
    };
    inline int sign(const double &x)
    {
    	if(x>epsi) return 1;
    	if(x<-epsi) return -1;
    	return 0;
    }
    inline double sqr( const double &x)
    {
    	return x*x;
    }
    inline double dis(const Point &p1,const Point &p2)
    {
    	return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));
    }
    inline double mul(const Point &p0,const Point &p1,const Point &p2)
    {
    	return (p1-p0)^(p2-p0);
    }
    inline int cross(const Point &p1,const Point &p2,const Point &p3,const Point &p4,Point &p)
    {
    	double a1=mul(p1,p2,p3),a2=mul(p1,p2,p4);
    	if(sign(a1)==0&&sign(a2)==0) return 2;//重叠
    	if(sign(a1-a2)==0) return 0;//平行
    	p.x=(a2*p3.x-a1*p4.x)/(a2-a1);
    	p.y=(a2*p3.y-a1*p4.y)/(a2-a1);
    	return 1;//相交
    }
    Point a[1100],s,e;
    struct node{
        double x,y,d;
    }b[1100];
    bool cmp(node a,node b){
        return a.d<b.d;
    }
    int main()
    {
        n=read,m=read;
        scanf("%lf%lf%lf%lf",&s.x,&s.y,&e.x,&e.y);
        rep(i,1,n){
            scanf("%lf%lf",&a[i].x,&a[i].y);
        }
        double FUCK=dis(s,e);
        rep(i,1,m){
            int idx=0,h=read,k=read;
            rep(j,1,n){
                if(j==h) continue;
                Point t;
                int flag=cross(a[h],a[j],s,e,t);
                if(flag&&dis(t,s)<=FUCK&&dis(t,e)<=FUCK){
                    b[++idx]={t.x,t.y,dis(t,s)};
                }
            }
            ///cout<<i<<"*******"<<idx<<endl;
            if(idx<k) puts("-1");
            else{
                sort(b+1,b+1+idx,cmp);
                printf("%.10lf %.10lf
    ",b[k].x,b[k].y);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    django自学
    Oracle
    Linux查看日志常用命令
    Appium使用
    jmeter性能测试
    数据库连接
    redis相关
    ubuntu系统软件安装以及相关命令
    LINUX远程强制重启/proc/sys/kernel/sysrq /proc/sysrq-trigger
    sqlserver查询表大小
  • 原文地址:https://www.cnblogs.com/OvOq/p/14853012.html
Copyright © 2011-2022 走看看