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; }