Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13254 | Accepted: 4217 |
Description
Input
Output
Sample Input
9 100 200 400 300 400 300 300 400 300 400 400 500 400 500 200 350 200 200 200
Sample Output
1628
Hint
Source
http://acm.pku.edu.cn/JudgeOnline/problem?id=1113
/* 计算几何,求凸包 这题的结果等于这个多边形构成的凸包的周长加上以所给半径为半径的圆的周长 步骤如下: 1)算法首先寻找最最靠下方的点,如果遇到y坐标相同,则寻找x坐标最小的点firstP 2)然后根据所有点相对于firstP的偏角的大小进行排序,遇到偏角相等的,只取距离 firstP最远的点(排序利用自己手写的快排) 3)然后利用Graham算法求凸包 4)最后直接求职 */ #include <iostream> #include <cmath> #define PI 3.1415926 #define MAX_N 1000 using namespace std; //存储原始输入的坐标值,rad是输入的半径 double cord[MAX_N + 2][2], rad; int seq[MAX_N + 2]; int stack[MAX_N + 2]; int n, top; int firstP; int realN; void swap(int pos1, int pos2) { int temp = seq[pos1]; seq[pos1] = seq[pos2]; seq[pos2] = temp; } int dir(int nodes, int node1, int node2) { double x1 = cord[node1][0], y1 = cord[node1][1]; double x2 = cord[node2][0], y2 = cord[node2][1]; double sx = cord[nodes][0], sy = cord[nodes][1]; return (x2 - sx) * (y1 - sy) - (x1 - sx) * (y2 - sy); } double getDist(int node1, int node2) { double x1 = cord[node1][0], y1 = cord[node1][1]; double x2 = cord[node2][0], y2 = cord[node2][1]; double res = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); return res; } int compare(int node1, int node2) { double x1 = cord[node1][0], y1 = cord[node1][1]; double x2 = cord[node2][0], y2 = cord[node2][1]; double sx = cord[firstP][0], sy = cord[firstP][1]; double type = dir(firstP, node1, node2); if(type == 0) { double dist1 = (x1 - sx) * (x1 - sx) + (y1 - sy) * (y1 - sy); double dist2 = (x2 - sx) * (x2 - sx) + (y2 - sy) * (y2 - sy); if(dist1 > dist2) return -2; else if(dist1 == dist2) return 0; else return 2; } else if(type > 0) return 1; else return -1; } void fastSort(int start, int end) { if(start < end) { int curPos = start; int posS = start, posE = end + 1; while(true) { while(compare(seq[++posS], seq[curPos]) < 0 && posS < end); while(compare(seq[--posE], seq[curPos]) > 0 && posE > start); if(posS < posE) swap(posS, posE); else break; } swap(curPos, posE); fastSort(start, posE - 1); fastSort(posE + 1, end); } } void sortSeq() { int i, s = 0; for(i = 1; i <= n; i++) { //最低最左点不参加排序 if(i == firstP) continue; seq[++s] = i; } realN = n - 1; fastSort(1, realN); //清理夹角相同但是距离不同的点,只取举例firstP最远的点 i = 1; while(i < realN) { s = i + 1; //equal angle but smaller distance while(s <= realN && compare(seq[i], seq[s]) == -2) { seq[s] = -1; //置为无效 s++; } i = s; } } //寻找凸包 void findQ() { int nodes, node1, node2, type; top = 0; stack[top++] = firstP; int s = 1; int c = 0; while(c < 2) { if(seq[s] != -1) { c++; stack[top++] = seq[s]; } s++; } for(; s <= realN; s++) { if(seq[s] == -1) continue; while(true) { nodes = stack[top - 2]; node1 = stack[top - 1]; node2 = seq[s]; type = dir(nodes, node1, node2); if(type >= 0) top--; else break; } stack[top++] = seq[s]; } } double getRes() { double totalDist = 0; int lastNode = firstP; int curNode; while(top > 0) { curNode = stack[--top]; totalDist += getDist(lastNode, curNode); lastNode = curNode; } //totalDist += getDist(lastNode, firstP); totalDist += 2 * PI * rad; return totalDist; } int main() { int i; cin>>n>>rad; int minX = INT_MAX, minY = INT_MAX; for(i = 1; i <= n; i++) { cin>>cord[i][0]>>cord[i][1]; if((cord[i][1] < minY) || (cord[i][1] == minY && cord[i][0] < minX)) { firstP = i; minX = cord[i][0]; minY = cord[i][1]; } } sortSeq(); findQ(); double res = getRes(); printf("%.0f/n", res); return 0; }