zoukankan      html  css  js  c++  java
  • [bzoj1074] [SCOI2007]折纸origami

    Description

      桌上有一张边界平行于坐标轴的正方形纸片,左下角的坐标为(0,0),右上角的坐标为(100,100)。接下来执行n条折纸命令。每条命令用两个不同点P1(x1,y1)和P2(x2,y2)来表示,执行时把当前的折纸作品沿着P1P2所在直线折叠,并把有向线段P1P2的右边折向左边(左边的部分保持不变)。折叠结束后,需要在作品上打一个孔,然后用绳子穿起来挂在墙上。孔的位置是相当重要的:若需要穿过太多层的纸,打孔本身比较困难;若穿过的层数太少,悬挂起来以后作品可能会被撕破。为了选择一个比较合适的打孔位置,你需要计算在每个候选位置打孔时穿过的层数。如果恰好穿过某一层的边界(误差0.000001内),则该层不统计在结果中。本题考虑一个简化的模型:纸的厚度不计,因此折纸操作总能完美执行。

    Input

      输入第一行为一个整数n,即折纸的次数。以下n行每行四个实数x1,y1,x2,y2,表示每次折纸时对应的有向线段。下一行包含一个正整数m,即候选位置的个数,以下每行包含两个实数x,y,表示一个候选位置。0<=n<=8, 1<=m<=50

    Output

      每个候选位置输出一行,包含一个整数,即该位置打孔时穿过的层数。

    Sample Input

    2
    -0.5 -0.5 1 1
    1 75 0 75
    6
    10 60
    80 60
    30 40
    10 10
    50 50
    20 50
    

    Sample Output

    4
    2
    2
    0
    0
    2
    

    solution

    计算几何。

    直接爆搜就好了。

    注意边界不能算进去,样例超级良心。

    中间要用到关于直线对称,我这里就直接(k_1k_2=-1),然后求交点啥的。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double 
    
    const int maxn = 2e5+10;
    const lf eps = 1e-8;
    
    struct point {
    	lf x,y;
    	point operator - (const point &rhs) const {return (point){x-rhs.x,y-rhs.y};}
    	lf operator ^ (const point &rhs) const {return x*rhs.y-y*rhs.x;}
    };
    
    struct line {
    	lf a,b,c;point x,y;
    	void init(lf x1,lf y1,lf x2,lf y2) {
    		x=(point){x1,y1},y=(point){x2,y2};
    		if(fabs(x1-x2)<eps) a=1,b=0,c=-x1;
    		else {
    			lf k=(y2-y1)/(x2-x1),B=y2-k*x2;
    			a=k,b=-1,c=B;
    		}
    	}
    }l[10];
    
    point inter(line a,line b) {
    	if(fabs(a.a)<eps) return (point){-b.c/b.a,-a.c/a.b};
    	if(fabs(a.b)<eps) return (point){-a.c/a.a,-b.c/b.b};
    	double y=(a.a*b.c-b.a*a.c)/(-a.a*b.b+a.b*b.a);
    	double x=(-a.c-a.b*y)/a.a;
    	return (point){x,y};
    }
    
    point flip(point a,line b) {
    	line c;c.a=-b.b,c.b=b.a;c.c=-(c.a*a.x+c.b*a.y);
    	point d=inter(b,c);
    	return (point){a.x+(d.x-a.x)*2.0,a.y+(d.y-a.y)*2.0};
    }
    
    int dfs(point a,int now) {
    	if(!now) return a.x>eps&&a.x<100-eps&&a.y>eps&&a.y<100-eps;
    	lf x=(l[now].x-a)^(l[now].y-a);
    	if(fabs(x)<eps) return 0;
    	if(x<-eps) return 0;
    	return dfs(a,now-1)+dfs(flip(a,l[now]),now-1);
    }
    
    int main() {
    	int n,m;read(n);
    	for(int i=1;i<=n;i++) {
    		lf x1,x2,y1,y2;scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    		l[i].init(x1,y1,x2,y2);
    	}
    	read(m);
    	for(int i=1;i<=m;i++) {
    		lf x,y;scanf("%lf%lf",&x,&y);write(dfs((point){x,y},n));
    	}
    	return 0;
    }
    
  • 相关阅读:
    CentOS随笔
    CentOS随笔
    CentOS随笔
    CentOS随笔
    产品从生到死的N宗罪
    即将结束的2015。
    Mvvm
    android 热补丁修复框架
    反编译APK
    关于短视频
  • 原文地址:https://www.cnblogs.com/hbyer/p/10421978.html
Copyright © 2011-2022 走看看