【poor几何】UVALive 5908 更新一下线段相交模板

题目点这

题意:给S个传感器,每个传感器范围为R,有W堵墙,碰到墙传感器范围会少1,给P个物品,问每个物品可以被几个传感器感受到。

思路:观察数据发现R很小,可以以每个点位中心扫描穷举,(暴力的不要不要的)。
在这里主要存一下新的线段相交模板,之前写过一篇跨立的题解,那个代码是直接从从原来用pascal的时候的代码翻译过来,丑的令人发指(自己调试都要吐血了)= =
这次重新写了struct,借chao鉴xi了 miss_minor 的跨立写法

#include<set>
#include<cmath>
#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm>
typedef long long LL;
using namespace std;

struct point{
    int x,y;
    point(int x=0,int y=0):x(x),y(y){}
    bool operator < (const point &a) const{
        return a.x==x ? y<a.y : x<a.x;
    }
    point operator + (const point &a)const{
        point ans;
        ans.x=x+a.x;
        ans.y=y+a.y;
        return ans;
    }
    point operator - (const point &a)const{
        point ans;
        ans.x=x-a.x;
        ans.y=y-a.y;
        return ans;
    }
    int   operator ^ (const point &a)const{
        return x*a.y-y*a.x;
    }
}po,tmp;

struct line{
    point a,b;
    void init(int ax=0,int ay=0,int bx=0,int by=0)
        {a.x=ax;a.y=ay;b.x=bx;b.y=by;}
}l[20];

int S,R,W,P,X1,X2,Y1,Y2;
vector<point>p;
set<point>vis;

LL dis(point a,point b){
    LL x=a.x-b.x,y=a.y-b.y;
    return x*x+y*y;
}

bool xj(point p1,point p2,point p3,point p4){//xiangjiao
    if (max(p1.x,p2.x)<min(p3.x,p4.x))return 0;
    if (max(p1.y,p2.y)<min(p3.y,p4.y))return 0;
    if (max(p3.x,p4.x)<min(p1.x,p2.x))return 0;
    if (max(p3.y,p4.y)<min(p1.y,p2.y))return 0;//ju xin shi yan

    LL x=(p3-p1)^(p2-p1);
    LL y=(p4-p1)^(p2-p1);
    LL z=(p1-p3)^(p4-p3);
    LL w=(p2-p3)^(p4-p3);//KuaLi
    return x*y<=0&&z*w<=0;
}

bool check(point a,point b){
    if (vis.find(b)==vis.end())return 0;
    LL d=dis(a,b);  if (d>R*R) return 0;
    int cnt=0;
    for (int i=0;i<W;i++)
        if (xj(a,b,l[i].a,l[i].b)) cnt++;
    if (cnt>R)return 0;
    return d<=(R-cnt)*(R-cnt); 
} 

int main(){
    //freopen("fuck.in","r",stdin);
    int T; scanf("%d",&T);
    for (;T--;){
        scanf("%d%d%d%d",&S,&R,&W,&P);
        vis.clear();
        for (int i=0;i<S;i++){
            scanf("%d%d",&po.x,&po.y);
            vis.insert(po);
        }
        for (int i=0;i<W;i++){
            scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
            l[i].init(X1,Y1,X2,Y2);
        } 
        for (int time=0;time<P;time++){
            scanf("%d%d",&po.x,&po.y);
            p.clear();
            for (int i=po.x-R;i<=po.x+R;i++)
                for(int j=po.y-R;j<=po.y+R;j++){
                    tmp.x=i; tmp.y=j;
                    if (check(po,tmp))p.push_back(tmp);
                }
            printf("%d",p.size());
            for (int i=0;i<p.size();i++)
                printf(" (%d,%d)",p[i].x,p[i].y);
            puts("");
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值