[POJ1265] Area 叉积求多边形面积+皮克定理 计算几何

Area
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7126   Accepted: 3059

Description

Being well known for its highly innovative products, Merck would definitely be a good target for industrial espionage. To protect its brand-new research and development facility the company has installed the latest system of surveillance robots patrolling the area. These robots move along the walls of the facility and report suspicious observations to the central security office. The only flaw in the system a competitor抯 agent could find is the fact that the robots radio their movements unencrypted. Not being able to find out more, the agent wants to use that information to calculate the exact size of the area occupied by the new facility. It is public knowledge that all the corners of the building are situated on a rectangular grid and that only straight walls are used. Figure 1 shows the course of a robot around an example area. 

 
Figure 1: Example area. 

You are hired to write a program that calculates the area occupied by the new facility from the movements of a robot along its walls. You can assume that this area is a polygon with corners on a rectangular grid. However, your boss insists that you use a formula he is so proud to have found somewhere. The formula relates the number I of grid points inside the polygon, the number E of grid points on the edges, and the total area A of the polygon. Unfortunately, you have lost the sheet on which he had written down that simple formula for you, so your first task is to find the formula yourself. 

Input

The first line contains the number of scenarios. 
For each scenario, you are given the number m, 3 <= m < 100, of movements of the robot in the first line. The following m lines contain pairs 揹x dy�of integers, separated by a single blank, satisfying .-100 <= dx, dy <= 100 and (dx, dy) != (0, 0). Such a pair means that the robot moves on to a grid point dx units to the right and dy units upwards on the grid (with respect to the current position). You can assume that the curve along which the robot moves is closed and that it does not intersect or even touch itself except for the start and end points. The robot moves anti-clockwise around the building, so the area to be calculated lies to the left of the curve. It is known in advance that the whole polygon would fit into a square on the grid with a side length of 100 units. 

Output

The output for every scenario begins with a line containing 揝cenario #i:� where i is the number of the scenario starting at 1. Then print a single line containing I, E, and A, the area A rounded to one digit after the decimal point. Separate the three numbers by two single blanks. Terminate the output for the scenario with a blank line.

Sample Input

2
4
1 0
0 1
-1 0
0 -1
7
5 0
1 3
-2 2
-1 0
0 -3
-3 1
0 -3

Sample Output

Scenario #1:
0 4 1.0

Scenario #2:
12 16 19.0

Source

Northwestern Europe 2001

传送门

大概题意:

默克公司以其高度创新的产品而闻名,这无疑是工业间谍活动的一个很好的目标。为了保护其全新的研发设施,该公司安装了最新的监控机器人巡逻系统。这些机器人沿着设施的墙壁移动,并向中央安全办公室报告可疑的观测结果。竞争对手代理人发现的系统中唯一的缺陷是机器人不加密地广播它们的运动。由于无法找到更多信息,该代理想要使用该信息来计算新设施占用的面积的确切大小。众所周知,建筑物的所有角落都坐落在一个长方形的网格上,只有直墙。图1显示了机器人围绕一个示例区域的过程。


你被雇来写一个程序,用来计算一个机器人沿着它的墙壁移动的新设备占用的面积。你可以假设这个区域是一个矩形网格上有角的多边形。然而,你的老板坚持说你用一个他很自豪的公式找到了某处。该公式涉及多边形内的网格点的数目i、边缘上的网格点的E和多边形的总面积A。不幸的是,你已经丢失了他为你写下简单公式的表格,所以你的第一项任务就是自己找到公式。

扫描二维码关注公众号,回复: 1613756 查看本文章

第一行包含场景的数目。

对于每一种情况,都给出了第一行中机器人运动的m,3 <=m<100。下面的M行包含整数的对x x Dy,由一个空格分隔,满足-- 100=dx,dy <=100和(dx,dy)!=(0, 0)。这样的一对意味着机器人在网格上(相对于当前位置)向上移动到网格点DX单元向右和Dy单元。你可以假设机器人移动的曲线是闭合的,除了起点和终点之外,它不相交甚至接触自身。机器人在建筑物周围逆时针移动,所以要计算的区域位于曲线的左边。预先知道,整个多边形将并入网格中的一个正方形,其边长为100个单位。

每一个场景的输出都是以包含塞纳里奥的第i行:i是从1开始的场景的数目。然后打印一条包含I、E和A的单行,小数点后的A区域为一位数。用两个单格分隔三个数字。用空行终止方案的输出。


题解:

本题其实是叉积求多边形面积+皮克定理的一道模板题。我们可以用叉积(x1*y2-x2*y1)/2算出这个多边形的面积S,同时我们还知道A(x1,y1)B(x2,y2)这条线段经过的整点数量edge其实是gcd(abs(x1-x2),abs(y1-y2)),然后再利用皮克定理算出多边形内部的整点数量inside:S=inside+edge/2-1 → inside=S-edge/2+1

AC代码:

#include<cstdio>
#include<iostream>
using namespace std;
struct node{
	int x,y;
}a[105];
int n;
int chaji(node x,node y){
	return x.x*y.y-x.y*y.x;
}
int gcd(int a,int b){
	if(b==0)return a;
	return gcd(b,a%b);
}
int ab(int x){
	return x>0?x:-x;
}
void work(){
	int x,y,in=0,edg=0,s=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i].x,&a[i].y);
		a[i].x+=a[i-1].x;a[i].y+=a[i-1].y;
	}
	a[n+1]=a[1];
	for(int i=1;i<=n;i++){
		s+=chaji(a[i],a[i+1]);
		edg+=gcd(ab(a[i].x-a[i+1].x),ab(a[i].y-a[i+1].y));
	}
	in=(s+2-edg)/2;
	printf("%d %d %.1lf\n\n",in,edg,double(s)/2.0);
}
int main(){
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++){
		printf("Scenario #%d:\n",i);
		work();
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/lvyanchang/article/details/80357722