luoguP4468 [SCOI2007]折纸

题意

似乎边界上(折线上、正方形纸片边上)的点认为是(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
",query((Point){x,y}));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/nofind/p/12244722.html