ZOJ--1010:Area(线段判交问题)

Area

Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge

Jerry, a middle school student, addicts himself to mathematical research. Maybe the problems he has thought are really too easy to an expert. But as an amateur, especially as a 15-year-old boy, he had done very well. He is so rolling in thinking the mathematical problem that he is easily to try to solve every problem he met in a mathematical way. One day, he found a piece of paper on the desk. His younger sister, Mary, a four-year-old girl, had drawn some lines. But those lines formed a special kind of concave polygon by accident as Fig. 1 shows.


Fig. 1 The lines his sister had drawn

"Great!" he thought, "The polygon seems so regular. I had just learned how to calculate the area of triangle, rectangle and circle. I'm sure I can find out how to calculate the area of this figure." And so he did. First of all, he marked the vertexes in the polygon with their coordinates as Fig. 2 shows. And then he found the result--0.75 effortless.


Fig.2 The polygon with the coordinates of vertexes

Of course, he was not satisfied with the solution of such an easy problem. "Mmm, if there's a random polygon on the paper, then how can I calculate the area?" he asked himself. Till then, he hadn't found out the general rules on calculating the area of a random polygon. He clearly knew that the answer to this question is out of his competence. So he asked you, an erudite expert, to offer him help. The kind behavior would be highly appreciated by him.


Input

The input data consists of several figures. The first line of the input for each figure contains a single integer n, the number of vertexes in the figure. (0 <= n <= 1000).

In the following n lines, each contain a pair of real numbers, which describes the coordinates of the vertexes, (xi, yi). The figure in each test case starts from the first vertex to the second one, then from the second to the third, ���� and so on. At last, it closes from the nth vertex to the first one.

The input ends with an empty figure (n = 0). And this figure not be processed.


Output

As shown below, the output of each figure should contain the figure number and a colon followed by the area of the figure or the string "Impossible".

If the figure is a polygon, compute its area (accurate to two fractional digits). According to the input vertexes, if they cannot form a polygon (that is, one line intersects with another which shouldn't be adjoined with it, for example, in a figure with four lines, the first line intersects with the third one), just display "Impossible", indicating the figure can't be a polygon. If the amount of the vertexes is not enough to form a closed polygon, the output message should be "Impossible" either.

Print a blank line between each test cases.


Sample Input

5
0 0
0 1
0.5 0.5
1 1
1 0
4
0 0
0 1
1 0
1 1
0


Output for the Sample Input

Figure 1: 0.75

Figure 2: Impossible


思路:这个题很明显,是个线段判交问题。。。先用跨立实验判断是否有相交的线段,若有则直接输出impossible、相反若没有则保留两位小数输出Area(注:这里面积输出要注意啊!我刚开始就是没注意这,让我想了半天 都没找到哪错了)

判断两条线断是否相交,首先我门要提出两个实验:

(1)快速排斥实验

(2)跨立实验

这两个实验的具体实现内容,大家可以看我的另一篇博客(是这个题的简化版): ZOJ--1648:Circuit Board(跨立实验线段判交)


最后 求面积的 就直接用叉乘的方法求。

叉乘:假设A、B、C、D四个点AB×CD=(A.x-B.x)*(C.y-D.y)-(A.y-B.y)*(C.x-D.x)


java AC代码:

import java.util.Scanner;

public class ZOJ_1010 {
	static int n,flag=0;
	static double arr[][]=new double[1000][2];
	public static void main(String[] args) {
		Scanner s=new Scanner(System.in);
		while((n=s.nextInt())!=0){
			for(int i=0;i<n;i++){
				arr[i][0]=s.nextDouble();
				arr[i][1]=s.nextDouble();
			}
			if(flag!=0)System.out.println();
			flag++;
			System.out.print("Figure "+flag+": ");
			if(n<3||!judge()){//少于3个点就围不成一个多边形
				System.out.println("Impossible");
				continue;
			}
			if(judge())
				System.out.printf("%.2f\n",area());
		}
	}
	public static boolean judge(){
		for(int i=3;i<n;i++){//不判断最后一条,因为最后一个点是从第n个点到第0个点
			for(int j=1;j<i-1;j++)
				if(cross(i-1,i,j-1,j))
					return false;
		}
		for(int i=2;i<n-1;i++){//判断最后一条
			if(cross(i-1,i,n-1,0))
				return false;
		}
		return true;
	}
	public static boolean cross(int i1,int i2,int j1,int j2){
		double a=cal(arr[i1][0]-arr[j1][0],arr[i1][1]-arr[j1][1],arr[j2][0]-arr[j1][0],arr[j2][1]-arr[j1][1]);
		double b=cal(arr[j2][0]-arr[j1][0],arr[j2][1]-arr[j1][1],arr[i2][0]-arr[j1][0],arr[i2][1]-arr[j1][1]);
		double c=cal(arr[j1][0]-arr[i1][0],arr[j1][1]-arr[i1][1],arr[i2][0]-arr[i1][0],arr[i2][1]-arr[i1][1]);
		double d=cal(arr[i2][0]-arr[i1][0],arr[i2][1]-arr[i1][1],arr[j2][0]-arr[i1][0],arr[j2][1]-arr[i1][1]);
		if(a*b>=0&&c*d>=0)
			return true;
		return false;
	}
	public static double cal(double a,double b,double c,double d){
		return a*d-c*b;
	}
	public static double area(){
		double area=0;
		for(int i=2;i<n;i++){
			area+=cal(arr[i-1][0]-arr[0][0],arr[i-1][1]-arr[0][1],arr[i][0]-arr[0][0],arr[i][1]-arr[0][1]);
		}
		return Math.abs(area)/2.0;
	}
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值