NC20253. [SCOI2007]折纸ORIGAMI
描述
输入描述
输入第一行为一个整数n,即折纸的次数。以下n行每行四个实数x1,y1,x2,y2,表示每次折纸时对应的有向线段。下一行包含一个正整数m,即候选位置的个数,以下每行包含两个实数x,y,表示一个候选位置。0 ≤ n ≤ 8, 1 ≤ m ≤ 50
输出描述
每个候选位置输出一行,包含一个整数,即该位置打孔时穿过的层数。
示例1
输入:
2 -0.5 -0.5 1 1 1 75 0 75 6 10 60 80 60 30 40 10 10 50 50 20 50
输出:
4 2 2 0 0 2
C++(clang++11) 解法, 执行用时: 6ms, 内存消耗: 380K, 提交时间: 2021-02-14 15:03:17
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; const int N=10; const double eps=1e-6,inf=0x3f3f3f3f; int n,m,ans; struct point{ double x,y; point operator-(point a){ return (point){x-a.x,y-a.y}; } double operator*(point a){ return x*a.y-a.x*y; } bool operator==(point a)const{ return (fabs(x-a.x)<eps&&fabs(y-a.y)<eps); } }; point no=(point){inf,inf},single=(point){-inf,-inf}; struct line{ point s,t; }l[N]; point turn(point a,line l){ double fg=(l.t-l.s)*(a-l.s); if(fg>eps){ point res; if(fabs(l.s.y-l.t.y)<eps){ res.x=a.x,res.y=l.s.y*2-a.y; } else if(fabs(l.s.x-l.t.x)<eps){ res.x=l.s.x*2-a.x,res.y=a.y; } else{ double k1=(l.s.y-l.t.y)/(l.s.x-l.t.x),b1=l.s.y-k1*l.s.x; double k2=-1/k1,b2=a.y-k2*a.x; double x=(b2-b1)/(k1-k2),y=k1*x+b1; res.x=x*2-a.x,res.y=y*2-a.y; } return res; } return no; } void dfs(point a,int now){ if(now==0){ if(a.x>eps&&a.x<100-eps&&a.y>eps&&a.y<100-eps){ ans++; } return; } point b=turn(a,l[now]); if(b==no)return; else{ dfs(a,now-1); dfs(b,now-1); } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%lf%lf%lf%lf",&l[i].s.x,&l[i].s.y,&l[i].t.x,&l[i].t.y); } scanf("%d",&m); point q; for(int i=1;i<=m;i++){ ans=0; scanf("%lf%lf",&q.x,&q.y); dfs(q,n); printf("%d\n",ans); } return 0; }