标签:operator scoi2007 code ble 关于 scan line c++ ons
似乎边界上(折线上、正方形纸片边上)的点认为是\(0\)。
由于操作次数很少,因此逆着操作,求出所有可能的点,之后正向模拟一遍判断即可。
求一个点关于一个向量的对称点:用向量旋转求出方向向量即可。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10;
const double eps=1e-8;
const double Pi=acos(-1.0);
const double inf=1e9;
int n,m;
struct Point
{
double x,y;
inline double len(){return sqrt(x*x+y*y);}
Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
Point operator*(const double k){return (Point){x*k,y*k};}
Point operator/(const double k){return (Point){x/k,y/k};}
double operator*(const Point a)const{return x*a.y-y*a.x;}
double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[1<<maxn];
inline int dcmp(double x)
{
if(fabs(x)<=eps)return 0;
return x<0?-1:1;
}
bool operator==(Point a,Point b){return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);}
inline Point get(Point a,Point b){return b-a;}
struct Line{Point p,v;}line[maxn];
inline bool cmp(Point a,Point b){return !dcmp(a.x-b.x)?dcmp(a.y-b.y)<0:dcmp(a.x-b.x)<0;}
inline Point turn(Point a,int op)
{
if(op==1)return (Point){-a.y,a.x};
else return (Point){a.y,-a.x};
}
inline bool check_left(Point a,Line b)
{
return dcmp(get(b.p,b.v)*get(b.p,a))>0;
}
inline bool check_right(Point a,Line b)
{
return dcmp(get(b.p,b.v)*get(b.p,a))<0;
}
inline Point rev(Point a,Line b,int op)
{
double h=fabs(get(a,b.p)*get(a,b.v))/get(b.p,b.v).len();
Point dir=turn(get(b.p,b.v),op);
return a+dir*(2*h/dir.len());
}
inline bool check_lim(Point a){return dcmp(a.x)>0&&dcmp(a.x-100)<0&&dcmp(a.y)>0&&dcmp(a.y-100)<0;}
inline Point work(Point a)
{
for(int i=1;i<=n;i++)
if(check_right(a,line[i]))a=rev(a,line[i],1);
else if(!check_left(a,line[i]))return (Point){-1,-1};
return a;
}
inline int query(Point a)
{
int tot=0;
p[++tot]=a;
for(int i=n;i;i--)
{
int tmp=tot;
for(int j=1;j<=tmp;j++)if(check_left(p[j],line[i]))p[++tot]=rev(p[j],line[i],2);
}
sort(p+1,p+tot+1,cmp);
int cnt=0;
p[0]=(Point){-inf,-inf};
for(int i=1;i<=tot;i++)if(dcmp(p[i].x-p[i-1].x)!=0||dcmp(p[i].y-p[i-1].y)!=0)p[++cnt]=p[i];
tot=cnt;
int res=0;
for(int i=1;i<=tot;i++)if(check_lim(p[i])&&work(p[i])==a)res++;
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf",&line[i].p.x,&line[i].p.y,&line[i].v.x,&line[i].v.y);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
double x,y;scanf("%lf%lf",&x,&y);
printf("%d\n",query((Point){x,y}));
}
return 0;
}
标签:operator scoi2007 code ble 关于 scan line c++ ons
原文地址:https://www.cnblogs.com/nofind/p/12244722.html