-
bzoj1074【Scoi2007】折纸
- 思路:考虑倒着做,每次将在折叠的直线右边的扔掉,左边的点再对称一次加入;
- 算几知识:求向量关于法向量的对称向量
- 点$A$关于点$B$对称的点$C = 2B - A$
- 如果要求$\vec{A}$关于法向量$\vec{l}$的对称向量$\vec{A'}$;
- 可以考虑都平移到原点
- 利用点积求出$\vec{A}$在$\vec{l}$上的投影点$D$, 再将点$A$关于$D$对称到$A'$;
- $A'$的坐标就是向量$\vec{A'}$
-
bzoj1074
1 #include<bits/stdc++.h> 2 #define db double 3 #define eps 1e-6 4 using namespace std; 5 const int N=1<<9; 6 int n,m,cnt,tmp; 7 int dcmp(db x){return fabs(x)<=eps?0:x<0?-1:1;} 8 struct point{ 9 db x,y; 10 point(db _x=0,db _y=0):x(_x),y(_y){}; 11 point operator +(const point&A)const{return point(x+A.x,y+A.y);} 12 point operator -(const point&A)const{return point(x-A.x,y-A.y);} 13 point operator *(const db&a)const{return point(x*a,y*a);} 14 db operator *(const point&A)const{return x*A.x+y*A.y;} 15 db operator ^(const point&A)const{return x*A.y-y*A.x;} 16 }p1[N],p2[N],q[N],qq[N]; 17 bool onleft(point A,point B,point C){ 18 return dcmp((C-B)^(A-B))>0; 19 } 20 point rev(point A,point B,point C){ 21 point D = C - B; 22 db l2 = D*D; 23 D = B + D*((A-B)*D/l2); 24 return D*2 - A; 25 } 26 int main(){ 27 #ifndef ONLINE_JUDGE 28 freopen("bzoj1074.in","r",stdin); 29 freopen("bzoj1074.out","w",stdout); 30 #endif 31 scanf("%d", &n); 32 for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf", &p1[i].x, &p1[i].y, &p2[i].x, &p2[i].y); 33 scanf("%d", &m); 34 for(int i=1;i<=m;i++){ 35 cnt=1;scanf("%lf%lf", &q[1].x, &q[1].y); 36 for(int j=n;j;j--){ 37 tmp=0; 38 for(int k=1;k<=cnt;k++)if(onleft(q[k],p1[j],p2[j])){ 39 qq[++tmp] = q[k]; 40 qq[++tmp] = rev(q[k],p1[j],p2[j]); 41 } 42 cnt=tmp; 43 if(!cnt)break; 44 for(int k=1;k<=cnt;k++)q[k]=qq[k]; 45 } 46 int ans=0; 47 // puts(""); 48 for(int j=1;j<=cnt;j++){ 49 // printf("%.2f %.2lf\n",q[j].x, q[j].y); 50 if(dcmp(q[j].x)>0&&dcmp(q[j].y)>0&&dcmp(100-q[j].x)>0&&dcmp(100-q[j].y)>0){ 51 ans ++; 52 } 53 } 54 printf("%d\n",ans); 55 } 56 return 0; 57 }
相关文章: