poj 3429 Geometry with a ruler

Geometry with a ruler
Time Limit: 3000MS Memory Limit: 65536K
Total Submissions: 1682 Accepted: 369

Description

Classic geometric construction is based on two instruments: ruler and compass. However, some constructions are possible using only the ruler. Specifically, let us define that if we have a set of N points, we can select two pairs of them, draw a line through each pair, and construct a new point as an intersection of these two lines. New point can then be added to the set as (N + 1)-th point, and the process repeated.

Such geometric constructions are abstract notions, and attempt to verify them with physical pencil and ruler can lead to errors caused by imprecision of these instruments. So you are tasked to write a program that does exact verification.

Your program must read a set of points and a sequence of constructing operations and find out whether the point with coordinates (0, 0) is one of the constructed points. Note that, similar to physical instruments, floating point calculations performed by computers are also imprecise. This should not, of course, alter verification results.

Input

Input file contains number of points N followed by their integer coordinates x1 y1 x2 y2 ... xN yN. Next comes number of construction operations M followed by M quads of integers ai bi ci di, where k-th quad means that a new point is constructed as an intersection of lines containing pairs of points aibi and cidi. Such a point is guaranteed to exist. Constructed point is assigned a number N + k and can be used in following operations.

Constraints

4 ≤ N ≤ 100, 1 ≤ M ≤ 10, −106 ≤ xiyi ≤ 106

Output

Output file must contain a single integer — number of the first operation which constructs a point (0, 0), or 0 (zero), if there is no such operation.

Sample Input

Sample Input 1
4
-1 -1  -2 2   2 2  1 -1
1
1 3 2 4
Sample Input 2
4
-1000 -1000  -2000 2000  2001 2000  1000 -1000
1
1 3 2 4

Sample Output

Sample Output 1
1
Sample Output 2
0

Hint

Bold texts appearing in the sample sections are informative and do not form part of the actual data.

Source

Northeastern Europe 2006, Far-Eastern Subregion

提示

题意:

给出n(4<=n<=100)个点,有m(1<=m<=10)组询问,每组给出a,b,c,d四个数,通过第a和第b个点和通过第c和第d个点的直线的交点如果是(0,0)输出当前是第几组,后面的数据不用处理,否则该交点加入点集中,输入保证合法。如果m组询问都没有得到(0,0),则输出0.

思路:

算法不难,难的是数据处理,这题要求的精度很高,所以用double几乎是不可能的,要么写成分数形式,要么化为整型,但坐标给的比较大需要用BigInteger。

我们在求交点时不是有:

x=(B1*C2-B2*C1)/(A1*B2-A2*B1)
y=(A2*C1-A1*C2)/(A1*B2-A2*B1)

那么我们把坐标放大:

x[i]*(A1*B2-A2*B1)

y[i]*(A1*B2-A2*B1)

就避免了浮点数的精度问题,之后就是大整数的运算。

示例程序

Source Code

Problem: 3429		Code Length: 1290B
Memory: 3144K		Time: 1813MS
Language: Java		Result: Accepted
import java.util.*;
import java.math.*;
public class Main
{
    public static void main(String[] args)
    {
    	Scanner in=new Scanner(System.in);
    	int m,i,i1,k,a,b,c,d,n;
    	BigInteger x[]=new BigInteger[110],y[]=new BigInteger[110],A1,B1,C1,A2,B2,C2;
    	k=1;
    	n=in.nextInt();
    	for(i=0;n>i;i++)
    	{
    		x[i]=in.nextBigInteger();
    		y[i]=in.nextBigInteger();
    	}
    	m=in.nextInt();
    	for(i=1;m>=i;i++)
    	{
    		a=in.nextInt();
    		b=in.nextInt();
    		c=in.nextInt();
    		d=in.nextInt();
    		if(k==0)				//输出第一次就行了,下面的就不管了
    		{
    			continue;
    		}
    		A1=y[b-1].subtract(y[a-1]);
    		B1=x[a-1].subtract(x[b-1]);
    		C1=y[a-1].multiply(x[b-1]).subtract(x[a-1].multiply(y[b-1]));
    		A2=y[d-1].subtract(y[c-1]);
    		B2=x[c-1].subtract(x[d-1]);
    		C2=y[c-1].multiply(x[d-1]).subtract(x[c-1].multiply(y[d-1]));
    		for(i1=0;n>i1;i1++)
    		{
    			x[i1]=x[i1].multiply(A1.multiply(B2).subtract(A2.multiply(B1)));	//坐标放大
    			y[i1]=y[i1].multiply(A1.multiply(B2).subtract(A2.multiply(B1)));
    		}
    		x[n]=B1.multiply(C2).subtract(B2.multiply(C1));
    		y[n]=A2.multiply(C1).subtract(A1.multiply(C2));
    		n++;
    		if(x[n-1].equals(BigInteger.ZERO)==true&&y[n-1].equals(BigInteger.ZERO)==true)	//判断
    		{
    			System.out.println(i);
    			k=0;					//表示已输出
    		}
    	}
    	if(k==1)			//没有输出
    	{
    		System.out.println(0);
    	}
    }
}
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值