ZOJ Problem Set - 1010

本文介绍了一种用于计算任意凸多边形面积的算法,并通过实例展示了如何利用该算法解决实际问题。文章详细阐述了算法的具体步骤、实现细节以及应用案例,旨在帮助读者理解和掌握此类几何计算技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Area

Time Limit: 1 Second      Memory Limit: 32768 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.

showImage.do?name=0000%2F1010%2F1010-1.jpg
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.

showImage.do?name=0000%2F1010%2F1010-2.jpg
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

 

1 #include <stdio.h>
2 #include <math.h>
3
4  #define MAXLENGTH 1000
5
6 typedef struct
7 {
8 double x, y;
9 }POI;
10 POI POINT[MAXLENGTH];
11 int N;
12 double AREA;
13
14 double ABS(double n)
15 {
16 return (n >= 0) ? n : -n;
17 }
18 double OUTER_PRODUCT(POI point_0, POI point_1, POI point_2)
19 {
20 return (point_1.x - point_0.x)*(point_2.y - point_0.y) - (point_2.x - point_0.x)*(point_1.y - point_0.y);
21 }
22 void COMPUTE()
23 {
24 int i;
25 AREA = 0;
26 for(i=1; i<N-1; i++)
27 AREA += OUTER_PRODUCT(POINT[0], POINT[i], POINT[i+1]);
28 }
29 int ON_SEGMENT(POI point_0, POI point_1, POI point_2)
30 {
31 double xMax = (point_1.x >= point_2.x) ? point_1.x : point_2.x;
32 double xMin = (point_1.x <= point_2.x) ? point_1.x : point_2.x;
33 double yMax = (point_1.y >= point_2.y) ? point_1.y : point_2.y;
34 double yMin = (point_1.y <= point_2.y) ? point_1.y : point_2.y;
35 if(point_0.x >= xMin && point_0.x <= xMax && point_0.y >= yMin && point_0.y <= yMax)
36 return 1;
37 else return 0;
38 }
39 int JUDGE_CROSS()
40 {
41 int i, j, lowerBound;
42 double d[4];
43 if(N < 3) return 1;
44 for(i=2; i<=N; i++)
45 {
46 lowerBound = (i == N) ? 2: 1;
47 for(j=lowerBound; j<i-1; j++)
48 {
49 d[0] = OUTER_PRODUCT(POINT[i-1], POINT[i], POINT[j-1]);
50 d[1] = OUTER_PRODUCT(POINT[i-1], POINT[i], POINT[j]);
51 d[2] = OUTER_PRODUCT(POINT[j-1], POINT[j], POINT[i-1]);
52 d[3] = OUTER_PRODUCT(POINT[j-1], POINT[j], POINT[i]);
53 /* 跨越测试成功 */
54 if(d[0]*d[1] < 0 && d[2]*d[3] <0)
55 return 1;
56 /* 否则共线,继续判断当前点是否在线上,否则不属于交叉 */
57 if(d[0] == 0 && ON_SEGMENT(POINT[j-1], POINT[i-1], POINT[i]))
58 return 1;
59 if(d[1] == 0 && ON_SEGMENT(POINT[j], POINT[i-1], POINT[i]))
60 return 1;
61 if(d[2] == 0 && ON_SEGMENT(POINT[i-1], POINT[j-1], POINT[j]))
62 return 1;
63 if(d[3] == 0 && ON_SEGMENT(POINT[i], POINT[j-1], POINT[j]))
64 return 1;
65 }
66 /* 当前线和上一相邻线都垂直x轴 */
67 if(POINT[i].x-POINT[i-1].x == 0 && POINT[i-1].x-POINT[i-2].x == 0 && ON_SEGMENT(POINT[i], POINT[i-1], POINT[i-2]))
68 return 1;
69 /* 当前线和上一相邻线斜率一样 */
70 else if((POINT[i].y-POINT[i-1].y) / (POINT[i].x-POINT[i-1].x) == (POINT[i-1].y-POINT[i-2].y) / (POINT[i-1].x-POINT[i-2].x) && ON_SEGMENT(POINT[i], POINT[i-1], POINT[i-2]))
71 return 1;
72 /* 注意到以上两个判断都必须加上对当前点是否在上一相邻线上的判断 */
73 }
74 return 0;
75 }
76
77 int main()
78 {
79 int i, count = 0;
80 while(scanf("%d", &N) && N != 0)
81 {
82 count ++;
83 for(i=0; i<N; i++)
84 scanf("%lf%lf", &POINT[i].x, &POINT[i].y);
85 POINT[N] = POINT[0];
86 if(count != 1) putchar(10);
87 if(JUDGE_CROSS() == 1)
88 {
89 printf("Figure %d: Impossible\n", count);
90 continue;
91 }
92 COMPUTE();
93 printf("Figure %d: %.2lf\n", count, ABS(AREA)/2);
94 }
95 }

附上测试数据:

5
0.01 0.01
0.01 1.01
0.51 0.51
1.01 1.01
1.01 0.01
4
0.01 0.01
0.01 1.01
1.01 0.01
1.01 1.01
4
0.01 0.01
1.01 0.01
2.01 1.01
2.01 0.01
5
0.01 0.01
2.01 0.01
2.01 1.01
1.01 0.01
0.01 1.01
4
0.01 0.01
1.01 -1.01
2.01 1.01
2.01 0.01
6
0.01 1.01
1.01 0.01
4.01 2.01
3.01 3.01
4.01 3.01
2.01 4.01
6
0.01 0.01
1.01 1.01
2.01 0.01
2.01 2.01
3.01 3.01
0.01 3.01
3
0.01 0.01
1.01 1.01
1.01 0.01

Figure 1: 0.75

Figure 2: Impossible

Figure 3: Impossible

Figure 4: Impossible

Figure 5: Impossible

Figure 6: 8.00

Figure 7: 5.50

Figure 8: 0.50

转载于:https://www.cnblogs.com/cjxa/archive/2010/04/23/1718527.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值