POJ 1788 Building a New Depot(计算正多边形边长)
http://poj.org/problem?id=1788
题意: ZOJ 2157
有一个多边形(可能是凹或凸),这个多边形的每条边都平行于坐标轴,且给出多边形所有顶点的坐标,每个顶点都是拐点(即连接该顶点的两边肯定相互垂直),现在要你输出该多边形的周长.
分析:
由于题目给出的该多边形的限制条件:平行坐标轴,每个点都是拐点. 那么可以得出结论:
对于每个X或Y坐标,该坐标上多边形的顶点数目一定是偶数个.(假设x=5坐标有多个顶点,那么顶点数一定是偶数,比如2个或4个或6个,不可能是奇数个)
对于某个坐标值X(或Y),如果该坐标值有偶数个点,那么该坐标上肯定有边,且从上到下相邻的两个点互连成边.如下图:
对于上图,可以自己对于用例画画,验证一下.
由上面两条结论,我们可以知道每个有多边形点的x或y坐标的边构造必然是: 坐标相邻的两个点连接成一条边即可,所以我们只要加上所有这些边即可.
首先把所有点坐标按X值排序,算出同一X值上的所有竖直的边长.
然后把所有点坐标按Y值排序,算出同一Y值上的所有水平的边长.
所有边长相加输出周长即可.
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
struct Point
{
int x,y;
}P[maxn];
bool compare_x(Point A,Point B)//升序排列
{
return A.x<B.x || (A.x==B.x&&A.y<B.y);
}
bool compare_y(Point A,Point B)
{
return A.y<B.y || (A.y==B.y&&A.x<B.x);
}
int main()
{
int n;
while(scanf("%d",&n)==1 && n)
{
for(int i=0;i<n;++i) scanf("%d%d",&P[i].x,&P[i].y);
int ans=0;
sort(P,P+n,compare_x);
for(int i=0;i<n;)
{
if(P[i].x==P[i+1].x)//计算竖直边
{
ans += P[i+1].y-P[i].y;
i+=2;
}
else ++i;
}
sort(P,P+n,compare_y);
for(int i=0;i<n;)
{
if(P[i].y==P[i+1].y)//计算水平边
{
ans+= P[i+1].x-P[i].x;
i+=2;
}
else ++i;
}
printf("The length of the fence will be %d units.\n",ans);
}
return 0;
}