1074: [SCOI2007]折纸origami - BZOJ
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度,再用那个点加上法向量的多少倍(用距离算一下)就是对称点了
思路倒是清晰,只是判重的时候傻×了一下,我本来是想排序后相同的就把前面的改掉,写着写着就变成把后边的改掉,答案就大了好多
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.