这可以说是一个凸包的模板题,之前的Graham扫描算法中还不是很懂其中叉积的作用,今天正好遇到这个题,那么就把前面的模板整理了一下:凸包判断_Graham扫描算法模板
题目意思
给出一个有N个点的多边形,在距离多边形为L的地方把多边形包围起来,计算包围起来需要的长度为多少?
那么这个题很明显就是一个凸包问题,那么处理拐角的地方,我们外面包围的长度和凸包的周长是相同的,我们将左右的拐角放在一起就是一个半径为L的圆,那么最终的周长也是可以求得的了
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 1100; const double PI = 3.1415926535; int n,l; struct Point { int x,y; }p[MAXN],c[MAXN]; double dis(Point a,Point b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } int mulit(Point p0,Point p1,Point p2) { return (p1.x - p0.x)*(p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x); } bool cmp(Point a,Point b) { int x = mulit(p[0],a,b); if(x > 0 || (x == 0 && dis(p[0],a) < dis(p[0],b)) )return true; return false; } int Graham() { int k = 0; for(int i = 1;i < n;i ++) if(p[i].y < p[k].y || (p[i].y == p[k].y && p[i].x < p[k].x)) k = i; swap(p[k],p[0]); sort(p+1,p+n,cmp); int tot = 1; c[0] = p[0],c[1] = p[1]; for(int i = 2;i < n;i ++) { while(tot && mulit(c[tot-1],c[tot],p[i]) <= 0) tot--; c[++tot] = p[i]; } return tot; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&l); for(int i = 0;i < n;i ++) scanf("%d%d",&p[i].x,&p[i].y); int tot = Graham(); double ans = 0; for(int i =0 ;i <= tot;i ++) ans += dis(c[i],c[(i+1)%(tot+1)]); ans += l*2*PI; printf("%.0lf\n",ans); if(T!=0) printf("\n"); } return 0; }