Peter and Bob are playing a “Points” game on a math sheet of paper. Peter places a few points on the paper — grid nodes. Bob wants to surround them with a polygon so that all marked nodes are lying strictly within (not at the border) the polygon. All sides of the polygon are along the sides or the diagonals of the grid cells and its perimeter is as small as possible. You must determine what is the perimeter of the polygon.
Input
The input file contains several test cases, each of them as described below.
The first line contains integer N — the number of points placed by Peter (1<N<100000). Each of following N lines contains two integers xi,yi — the point coordinates placed by Peter. The coordinates by absolute value do not exceed 10 6. Some points can match.
Output
For each test case, you need to print one number — the perimeter of the required polygon, on a line by itself. The answer should be printed with accuracy not less than 0.001.
Sample Input
1
Input
The input file contains several test cases, each of them as described below.
The first line contains integer N — the number of points placed by Peter (1<N<100000). Each of following N lines contains two integers xi,yi — the point coordinates placed by Peter. The coordinates by absolute value do not exceed 10 6. Some points can match.
Output
For each test case, you need to print one number — the perimeter of the required polygon, on a line by itself. The answer should be printed with accuracy not less than 0.001.
Sample Input
1
0 0
2
1 1
1 2Sample Output
5.656
7.656854
题目大意:二维的网格平面上有N个点,要用一个封闭的折线去把所有的点包起来(不能在边界上),然后折线一定要是网格的边或者是某个网格的对角线,求最小的折线的长。
题解:
乍一看是凸包题。因为所有的点都不能在折线的边界上,所有对每个点向上下左右四个方向都多加一个点。然后对所有的点求凸包就好了。
但是,最后的折线并不是一个凸包..比如这组样例 :
2
1 1
3 2
答案不是sqrt(2)*4+sqrt(6)*2;而是sqrt(2)*6+2. 因为点(1,2)不能和点(3,3)直接相连,要由两条折线相连。
#include <stdio.h> #include <math.h> #include <set> #include <algorithm> #include <stack> using namespace std; const int maxn=100005; int gox[4]={0,0,1,-1}; int goy[4]={1,-1,0,0}; struct point { int x; int y; friend bool operator<(point a,point b) { if (a.y!=b.y) return a.y<b.y; return a.x<b.x; } point (int _x=0,int _y=0) { x=_x; y=_y; } }p[maxn*4]; set<point>s; set<point>::iterator it; stack<point>sta; long long dis(point a,point b) { long long x=a.x-b.x; long long y=a.y-b.y; return x*x+y*y; } double disc(point a,point b) { long long x=abs(a.x-b.x); long long y=abs(a.y-b.y); long long c=(x>y?y:x); x-=c; y-=c; return sqrt(2*c*c)+x+y; } bool comp(point a,point b) { long long x1=a.x-p[0].x; long long x2=b.x-p[0].x; long long y1=a.y-p[0].y; long long y2=b.y-p[0].y; if (x1*y2-x2*y1!=0) return x1*y2-x2*y1<0; return dis(a,p[0])<dis(b,p[0]); } bool check(point a,point b,point c) { long long x1=b.x-a.x; long long x2=c.x-a.x; long long y1=b.y-a.y; long long y2=c.y-a.y; if (x1*y2-x2*y1!=0) return x1*y2-x2*y1<0; return dis(a,c)>dis(a,b); } int main() { int n,x,y; point tem; double ans=0; while (~scanf("%d",&n)) { s.clear(); while (!sta.empty()) sta.pop(); for (int i=0;i<n;i++) { scanf("%d%d",&x,&y); for (int j=0;j<4;j++) s.insert(point(x+gox[j],y+goy[j])); } it=s.begin(); n=s.size(); for (int i=0;i<n;i++) { p[i]=*it; it++; } sort(p+1,p+n,comp); sta.push(p[0]); tem=p[1]; for (int i=2;i<n;i++) { while (!check(sta.top(),tem,p[i])) { tem=sta.top(); sta.pop(); } sta.push(tem); tem=p[i]; } ans=disc(tem,p[0]); while (!sta.empty()) { ans+=disc(tem,sta.top()); tem=sta.top(); sta.pop(); } printf("%.10lf\n",ans); } return 0; }