NOJ1070南邮仙林自行车停放场——计算几何+多边形_tcherry的博客-程序员秘密

技术标签: C++  ACM  

南邮仙林自行车停放场

Time Limit(Common/Java):1000MS/3000MS          Memory Limit:65536KByte
Total Submit:417            Accepted:72

Description

好消息!南邮规划建设自行车停放场,现已选定多个场地,它们均为规则多边形。现请你帮助学校确定哪块场地面积最大,这里以鼎山之顶为平面坐标原点,按顺时针或逆时针给出顶点坐标。

Input

输入数据中含有一些多边形场地(1≤数量≤20),按输入顺序编号(从1开始)。每个多边形场地的第一行数据n3n10),后续n行分别给出顶点的平面坐标(平面两个坐标的绝对值≤50)。

Output

输出面积最大的多边形场地序号。当面积最大的多边形场地有多个时,输出这些场地中的最小序号

Sample Input

2
3
0 0
0 1
1 0
4
0 0
0 1
1 1
1 0

Sample Output

2

Source

“IBM南邮杯”个人赛2009


分析:用了模板。模板写的真好!

附:多边形面积求法:

方法一:三角形法(最常用)
基本思想为: 
    把有n个顶点的多边形分成n个三角形,分别求得面积后求和,即得到多边形的面积。 
具体操作如下: 
   设多边形的顶点为P1,P2,...,Pn;另任取一点P0,与上述顶点组成n个三角形P0P1P2,   P0P2P3,   ...P0Pn-1Pn,P0PnP1。分别求得这n个三角形的面积为S1,S2,...,Sn;则多变形的面积为S=S1+S2+...+Sn 
为了简化计算,可以将多边形的某个点定义为P0;
三角形的面积公式: 
   设三角形的三个顶点的坐标为(x1,y1),(x2,y2),(x3,y3);   三角形的面积为s;则有如下公式成立 


        |   1   x1   y1   | 

 2s=  |   1   x2   y2   |        

        |   1   x3   y3   |

struct Point // 点结构体
{ 
	int x, y;
};

// 点的叉积: AB * AC
int cross(const Point &A, const Point &B, const Point &C) 
{
	return (B.x - A.x) * (C.y - A.y) - (B.y - A.y) * (C.x - A.x);
}

/*
* 计算多边形面积
* 参数:n个顶点, 多边形顶点坐标集合
*/
double polygon_area(const int &n, Point p[])
{
	double area = 0.0;
	int i;
	Point temp;

	temp.x = temp.y = 0; // 原点
	for (i = 0; i < n-1; ++i){
		area += cross(temp, p[i], p[i+1]);
	}
	area += cross(temp, p[n-1], p[0]); // 首尾相连
	area = area/2.0;        // 注意要除以2
	return area > 0 ? area : -area;    // 返回非负数
}

方法二:积分法(要考虑分段积分,复杂)
现在要求的多边形是由线段组成的,只要把所有的线段都求定积分,最后把和加起来,
就是多边形的面积。
这个推论的证明从略。值得注意的是,用定积分求的面积有正负之分,即:
b         a
∫f(x)dx=-∫f(x)dx
a         b
从a积到b,与从b积到a只相差一个负号。


  线段定积分的计算公式的推导


给出两个点,如何求这两点连成的线段的定积分值呢?
直线的方程可以用y=kx+b表示,所以围成的面积
S=

x2
∫(kx+b)dx = k/2(x2^2-x1^2)+b(x2-x1) 
x1

而斜率k=(y2-y1)/(x2-x1)
截距b=y1-kx1=y1-x1(y2-y1)/(x2-x1),代入前式得
S=(y2-y1)(x2+x1)/2+y1(x2-x1)-x1(y2-y1)
=(x2-x1)(y1+y2)/2
方法三:边长计算方法
也是拆分成三角形,只是三角形的计算方法用三边距离公式:
三角形的面积求法是S=sqr(p*(p-a)*(p-b)*(p-c)),其中,p=(a+b+c)/2,a、b、c为边长,a=sqr((x1-x2)^2+(y1-y2)^2) 



此题完整代码:(模板)

#include<iostream>
#include<cmath> // !!!
#include<string>
using namespace std;

//南邮仙林自行车停放场

struct POLY // 多边形,顺时针或逆时针给出x,y
{
	int n;
	double * x;
	double * y;
	POLY() : n(0), x(NULL), y(NULL) {}; // 无参构造
	POLY(int _n_ , const double * _x_, const double * _y_) // 带参构造
	{
		n = _n_;
		x = new double[n + 1];
		memcpy(x, _x_, n * sizeof(double));
		x[n] = _x_[0]; // 首尾要重合
		y = new double[n + 1];
		memcpy(y, _y_, n * sizeof(double));
		y[n] = _y_[0];
	}
};
double Area(const POLY & poly) // 求多边形面积
{
	if(poly.n < 3) return double(0);
	double s = poly.y[0] * (poly.x[poly.n - 1] - poly.x[1]);
	for(int i=1;i<poly.n;i++)
		s += poly.y[i] * (poly.x[i - 1] - poly.x[(i + 1) % poly.n]);
	return fabs(s/2); // 会有负数
}

int main()
{
	int N;
	POLY poly[21];
	double area[21];
	scanf("%d",&N);
	for(int i=1;i<=N;i++)
	{
		int n; // 几个点
		double x[10];
		double y[10];
		scanf("%d",&n);
		for(int i=0;i<n;i++)
			scanf("%lf%lf",&x[i],&y[i]);
		poly[i] = POLY(n, x, y);
		area[i] = Area(poly[i]);
	}
	double max = 0.0;
	int number;
	for(int i=1;i<=N;i++)
	{
		//	printf("%f ",area[i]);
		if(max < area[i])
		{
			max = area[i];
			number = i;
		}
	}
	printf("%d\n",number);
	return 0;
}

另一种简便的写法:
#include<iostream>
#include<cmath>
using namespace std;

struct Point
{double x, y;};

double area_polygon(int n, Point *p)
{
	double s1 = 0, s2 = 0;
	for(int i=0;i<n;i++)
		s1 += p[(i+1)%n].y * p[i].x, s2 +=  p[(i+1)%n].y * p[(i+2)%n].x; // 还能这样写!!!
	return fabs(s1 - s2) / 2;
}

int main()
{
	int ncases, n, max = -1;
	double s, maxs = -1;
	cin>>ncases;
	for(int i=0;i<ncases;i++)
	{
		cin>>n;
		double x, y;
		Point *p = new Point[n];
		for(int j=0;j<n;j++)
		{
			cin>>x>>y;
			p[j].x = x;
			p[j].y = y;
		}
		s = area_polygon(n, p);
		if(maxs < s)
		{
			max = i;
			maxs = s;
		}
	}
	cout<<max+1;

	return 0;
}



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/tcherry/article/details/32705907

智能推荐

hadoop平台进行小型网站的日志分析_老三是只猫的博客-程序员秘密

转载连接0.上传日志文件到linux中,通过flume将文件收集到hdfs中。执行命令/home/cloud/flume/bin/flume-ng agent -n a4 -c conf -f /home/cloud/flume/conf/a4.conf -Dflume.root.logger=DEBUG,console1.建立hive表create external table bbslog

linux系统安装yum教程,RedHat安装yum的方法总结_文清的男友的博客-程序员秘密

最近配置了服务器需要安装软件方法有几种。1.下载软件包 ,编译安装 (./configure,make,make install)这样安装配置性更高。相信高手都是这样安装的。2.yum安装。这样安装起来比较简单。(yum install 软件包名称) 主要适用于(CentOS,Red Hat)等.卸载:yum remove 软件包名称.3.apt-get 安装 这个和yum安装差不多。(sudo...

Non-static method cannot be referenced from a static context_蜡笔小新hyp的博客-程序员秘密

问题描述:public class ActivityA extends Activity implements OnClickListener {private String a="XX";private String b="XX";@Overridepublic void onClick(View v){switch(){case a:boolean isCh

3.依赖倒置原则_依赖倒转原则优点_云策数据的博客-程序员秘密

目录目录3依赖倒置原则1依赖倒置原则的定义2 言而无信你太需要契约3依赖的三种写法构造函数传递依赖对象Setter方法传递依赖对象接口声明依赖对象4 最佳实践快捷键Markdown及扩展表格定义列表代码块脚注目录数学公式UML 图离线写博客浏览器兼容3依赖倒置原则3.1依赖倒置原则的定义依赖倒置原则(Dependence Inversion Principle,

【图像增强】基于matlab GUI暗通道+Retinex图像去雾(带面板)【含Matlab源码 732期】_matlab图像去雾retinex_海神之光的博客-程序员秘密

1 暗通道先验图像去雾方法1.1 光线透射率模型光在传播中由于散射使得从光源发出的辐射只有部分能到达接收传感器,其他则被散射到传播介质中。假设距离较小时散射光强与距离是线性关系,当光源距离传感器无限接近时,光的衰减值可近似为:Br,其中β为空气的散射系数;r为光源与传感器间的距离。大气密度均匀时,光线透射率的数学模型为:式中:D为场景深度;t为光线透射率,用于量化传感器接收光强与光源表面光强间的比例关系,即没有被散射的辐射与光源辐射间的比例关系。1.2 暗通道先验理论。

tab切换_这就是我的昵称j的博客-程序员秘密

vue中:通过点击找到当前元素的下标 给它加上不同样式的类名在jQuery中:.actives{ color: pink;}

随便推点

windows命令行大全_weixin_30314813的博客-程序员秘密

命令简介cmd是command的缩写.即命令行 。虽然随着计算机产业的发展,Windows 操作系统的应用越来越广泛,DOS 面临着被淘汰的命运,但是因为它运行安全、稳定,有的用户还在使用,所以一般Windows 的各种版本都与其兼容,用户可以在Windows 系统下运行DOS,中文版Windows XP 中的命令提示符进一步提高了与DOS 下操作命令的兼容性,用户可以在命令提示符直接输入...

分布式与集群的区别_天天向上99的博客-程序员秘密

简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。  例如:  如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在一台服务器上执行改任务需10小时。  采用分布式方案,提供10台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工作模式的一个典型代表就是H

叠加定理和戴维宁定理_戴维宁定理和叠加定理的区别_莫余的博客-程序员秘密

叠加定理线性电路的任一条支路的电流,等于电路中各个电源单独作用时(其余电源置零) ,在该支路产生的电流的代数和。使用时注意事项:叠加定理只适用于线性电路。线性电路的电流或电压均可用叠加定理计算,但功率P不能用叠加定理计算。不作用电源的处理:E=0,即将E短路; I=0,即将I开路。解题时要标明各支路电流、电压的参考方向。戴维宁定理(应用于负载变化、桥型电路)二端网络:具有两个出线端的部分电路。有源二端网络:二端网络中含有电源。无源二端网络:二端网络中没有电源。任何一个线性有源

Quartz使用大全 (翻译自官方文档)_quartz官方文档_黄金时代的架构之路的博客-程序员秘密

http://www.quartz-scheduler.org/documentation/quartz-2.2.2/tutorials/tutorial-lesson-01.html1.使用QuartzQuartz Scheduler一旦关闭,无法重启需要重新实例化提供了暂停状态SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();Scheduler sched = schedFact.getS

Windows上的Telnet相关程序_fw0124的博客-程序员秘密

Windows上的Telnet相关程序有以下3个,位于C:\WINDOWS\system32:1)telnet.exe客户端程序。2)tlntsvr.exe服务器程序,运行它启动一个telnet服务器.3)tlntadmn.exetelnet服务器管理程序. 例如把telnet端口从默认的23改成9000:tlntadmn config port=9000。C:\>

在ubuntu中使用iscsi网络磁盘。_ubuntu怎么登录iscsi_邹德强的博客-程序员秘密

ISCSI网络磁盘协议已经广泛应用,在Win7中已经预置客户端。在ubuntu下怎么能自由的访问ISCSI的 targets呢?打开终端1.安装ISCSI支持sudo apt-get install open-iscsi2.看看服务器支持了多少个target (将192.168.0.1:3260替换为你的 IP:Port)sudo iscsiadm -m discovery