zoukankan      html  css  js  c++  java
  • 1074: [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,表示一个候选位置。
    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


    HINT

    样例说明 【限制】 20%的数据满足:n<=1 100%的数据满足:0<=n<=8, 1<=m<=50

    话说我也不知道我怎么就想到了这个想法

    对于每个询问,我们可以暴力求出它穿过的点原来是在什么位置,因为n<=8,所以最多有2^8个点,然后排序判重(话说我排序只是为了好判重)

    再对每一个点做一遍那n个操作,看是不是落在现在这个点,是的话ans+1

    然后就做完了

    求对称点的话,我是用向量求的,用向量可以很容易计算出距离,然后求直线的法向量,就是直接旋转90度,再用那个点加上法向量的多少倍(用距离算一下)就是对称点了

    思路倒是清晰,只是判重的时候傻×了一下,我本来是想排序后相同的就把前面的改掉,写着写着就变成把后边的改掉,答案就大了好多

      1 const
      2     eps=1e-6;
      3 type
      4     segment=record
      5       x1,y1,x2,y2:double;
      6     end;
      7     point=record
      8       x,y:double;
      9     end;
     10 var
     11     n,m:longint;
     12     a:array[0..8]of segment;
     13     b:array[0..300]of point;
     14 
     15 function cj(x1,y1,x2,y2:double):double;
     16 begin
     17     exit(x1*y2-y1*x2);
     18 end;
     19 
     20 procedure init;
     21 var
     22     i:longint;
     23 begin
     24     read(n);
     25     for i:=1 to n do
     26       with a[i] do
     27         read(x1,y1,x2,y2);
     28 end;
     29 
     30 procedure swap(var x,y:point);
     31 var
     32     t:point;
     33 begin
     34     t:=x;x:=y;y:=t;
     35 end;
     36 
     37 procedure sort(l,r:longint);
     38 var
     39     i,j:longint;
     40     y:point;
     41 begin
     42     i:=l;
     43     j:=r;
     44     y:=b[(l+r)>>1];
     45     repeat
     46       while (b[i].x<y.x) or ((b[i].x=y.x)and(b[i].y<y.y)) do
     47         inc(i);
     48       while (b[j].x>y.x) or ((b[j].x=y.x)and(b[j].y>y.y)) do
     49         dec(j);
     50       if i<=j then
     51       begin
     52         swap(b[i],b[j]);
     53         inc(i);
     54         dec(j);
     55       end;
     56     until i>j;
     57     if i<r then sort(i,r);
     58     if j>l then sort(l,j);
     59 end;
     60 
     61 procedure get(b:point;c:segment;var a:point);
     62 var
     63     d:double;
     64 begin
     65     a.x:=c.y1-c.y2;
     66     a.y:=c.x2-c.x1;
     67     d:=cj(c.x2-c.x1,c.y2-c.y1,b.x-c.x1,b.y-c.y1)/sqrt(sqr(c.x1-c.x2)+sqr(c.y1-c.y2));
     68     a.x:=a.x/sqrt(sqr(c.x1-c.x2)+sqr(c.y1-c.y2));
     69     a.y:=a.y/sqrt(sqr(c.x1-c.x2)+sqr(c.y1-c.y2));
     70     a.x:=b.x-a.x*d*2;
     71     a.y:=b.y-a.y*d*2;
     72 end;
     73 
     74 procedure work;
     75 var
     76     i,j,k,num,ans:longint;
     77 begin
     78     read(m);
     79     for i:=1 to m do
     80       begin
     81         ans:=0;
     82         with b[1] do
     83           read(x,y);
     84         b[0]:=b[1];
     85         num:=1;
     86         for j:=n downto 1 do
     87           begin
     88             for k:=1 to num do
     89               get(b[k],a[j],b[k+num]);
     90             num:=num<<1;
     91           end;
     92         sort(1,num);
     93         for j:=2 to num do
     94           if (abs(b[j].x-b[j-1].x)<eps) and (abs(b[j-1].y-b[j].y)<eps) then b[j-1].x:=100000;
     95         for j:=1 to num do
     96           if not((b[j].x>eps) and (b[j].x+eps<100) and (b[j].y>eps) and (b[j].y+eps<100)) then b[j].x:=1000
     97           else
     98           for k:=1 to n do
     99             if abs(cj(a[k].x2-a[k].x1,a[k].y2-a[k].y1,b[j].x-a[k].x1,b[j].y-a[k].y1))<eps then b[j].x:=1000000
    100             else
    101             if cj(a[k].x2-a[k].x1,a[k].y2-a[k].y1,b[j].x-a[k].x1,b[j].y-a[k].y1)<0 then get(b[j],a[k],b[j]);
    102         for j:=1 to num do
    103           if (abs(b[j].x-b[0].x)<eps) and (abs(b[j].y-b[0].y)<eps) then inc(ans);
    104         writeln(ans);
    105       end;
    106 end;
    107 
    108 begin
    109     init;
    110     work;
    111 end.
    View Code
  • 相关阅读:
    分布式配置中心选型
    springboot中后端返回数据给前端的设计模式
    java中泛型在静态方法中的使用
    java在开发中DO、DTO、BO、AO、VO、POJO定义
    linux中find命令的使用详解(转载)
    Centos7配置ssh免密登录群发
    关于oracle PL/SQL存储过程 PLS-00905 object is invalid,statement ignored问题的解决
    Django-ModelFrom中修改save后的字段值
    MongoDB的集群模式--Sharding(分片)
    MongoDB用户和密码登录
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3629347.html
Copyright © 2011-2022 走看看