题意
似乎边界上(折线上、正方形纸片边上)的点认为是\(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; }
来源:https://www.cnblogs.com/nofind/p/12244722.html