• BZOJ 1074: [SCOI2007]折纸origami


    1074: [SCOI2007]折纸origami

    Time Limit: 20 Sec  Memory Limit: 162 MB

    Submit: 354  Solved: 212

    [Submit][Status][Discuss]

    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

    题解

    对于每个询问,将点倒着操作一步步展开,判断最后有多少个存在的点即可。

    代码

    #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
    ",ans);
    	}
    	return 0;
    }
  • 相关阅读:
    ubuntu12.04 死机 卡屏 画面冻结解决方案
    Install Firefox 20 in Ubuntu 13.04, Ubuntu 12.10, Ubuntu 12.04, Linux Mint 14 and Linux Mint 13 by PPA
    ListView1.SelectedItems.Clear()
    android studio 下载地址
    jquery.slider.js jquery幻灯片测试
    jquery.hovermenu.js
    jquery.tab.js选项卡效果
    适配 placeholder,jquery版
    jquery.autoscroll.js jquery自动滚动效果
    将 Google Earth 地图集成到自己的窗体上的 简单控件
  • 原文地址:https://www.cnblogs.com/chezhongyang/p/7763447.html
Copyright © 2020-2023  润新知