poj1265——pick定理+点在多边形上的个数

题目链接:http://poj.org/problem?id=1265

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

题目翻译:

默克以其高度创新的产品而闻名,绝对是工业间谍的好目标。为了保护其全新的研发设施,该公司安装了最新的监视机器人系统,在该地区巡逻。这些机器人沿着设施的墙壁移动,并将可疑观测报告给中央安全办公室。竞争对手的代理能够发现系统中唯一的缺陷是,机器人在未加密的无线电中广播其移动。由于无法发现更多,代理希望使用该信息来计算新设施占用区域的确切大小。公众知道,建筑物的所有角落都位于一个矩形网格上,并且只使用直墙。图 1 显示了机器人围绕示例区域的过程。‎



‎图 1:示例区域。‎


‎您被雇用编写一个程序,从机器人沿其墙壁的运动计算新设施占用的区域。可以假定此区域是矩形网格上具有角的多边形。然而,你的老板坚持说,你使用一个公式,他很自豪找到某处。公式关联多边形内网格点数 I、边上的网格点数和面的总面积 A。不幸的是,你丢失了他为你写下简单公式的表格,所以你的首要任务是自己找到公式。‎

‎输入‎

‎第一行包含方案数。‎
‎对于每个方案,都会为机器人在第一行中的移动次数 m、3 <& m< 100) 提供。以下 m 线包含整数的对 [x dy》,由单个空白分隔,满足 .-100 <= dx,dy <= 100 和 (dx, dy) != (0, 0)。这种对意味着机器人移动到右侧的网格点 dx 单位,并在网格上向上移动 dy 单位(相对于当前位置)。您可以假定机器人移动的曲线是闭合的,并且除了起点和终点外,它不相交甚至触摸自身。机器人在建筑物周围逆时针移动,因此要计算的区域位于曲线的左侧。事先知道,整个多边形将适合网格上的一个正方形,侧面长度为 100 个单位。‎

‎输出‎

‎每个方案的输出都以一行包含 "cenario #i开头:其中 i 是方案的编号,从 1 开始。然后打印包含 I、E 和 A 的单行,该区域 A 在小数点之后四舍五入为一位数字。将三个数字除以两个空格。使用空行终止方案的输出。

 

题意理解:起点是(0,0),给你一些坐标,依次表示x,y移动的单位后的点,求这些点构成的凸多边形内的整点个数。

这个题需要用到pick定理:S=a+b/2−1。

其中a表示多边形内部的整点数,b表示多边形边界上的整点数,S表示多边形的面积。

然后就可以转化成a=S-b/2+1,我们只需要求出在多边形上的整点的个数和多边形面积就行了。

面积可以把多边形分成n-2个三角形然后用叉乘求。

多边形上的整点的个数可以转化成求多边形各条边上的整点的个数和。

需要用到一个结论:求(x1,y1)和(x2,y2)组成的线段上的整点个数等于gcd(abs(x1-x2),abs(y1-y2))+1。

证明没有百度到详细的,自己推几个例子。

#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
struct Point{
	int x,y;
	Point(int x=0,int y=0):x(x),y(y){}
}p[105];
typedef Point Vector;
Vector operator-(Point a,Point b){
	return Vector(a.x-b.x,a.y-b.y);
}
int Cross(Point a,Point b){
	return a.x*b.y-a.y*b.x;
} 
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b); 
}
int main(){
	int T,m;
	scanf("%d",&T);
	for(int kcase=1;kcase<=T;kcase++){
		scanf("%d",&m);
		int n=0;
		p[n].x=0,p[n++].y=0;
		int x=0,y=0,dx,dy,cnt2=0;
		for(int i=0;i<m;i++){
			scanf("%d%d",&dx,&dy);
			x+=dx;
			y+=dy;
			p[n].x=x;
			p[n++].y=y;
			cnt2+=gcd(abs(dx),abs(dy));
		}
		int sum=0;
		for(int i=0;i<n;i++)
			sum+=Cross(p[i]-p[0],p[(i+1)%n]-p[0]);
		double S=abs(sum)*1.0/2;
		int cnt1=S-cnt2/2+1;
		printf("Scenario #%d:\n%d %d %.1f\n\n",kcase,cnt1,cnt2,S);
	}	
	return 0;
}

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值