因为涉及到旋转和夹角,所以运用到了叉积。
例子:
hdu 1348 wall
http://acm.hdu.edu.cn/showproblem.php?pid=1348
大致题意:给出N个点,它所形成的多边形向外撑长L,新的多边形的周长是多少?
分析:每对对顶角的和是180度,n多边形有n个顶点,同时多边形的内角和是180(n-2),那么外围的夹角和就应该是180n-180(n-2)=360
于是得到结论:多边形的周长+圆的周长就是所求。
#include <iostream> #include <cmath> #include <cstdio> #include <algorithm> using namespace std; struct point{ int x,y; }pt[1005]; int sta[1005],ans[1005],cnt; int cmp(point a,point b){ //左下角优先 先左再下 return a.x<b.x||(a.x==b.x&&a.y<b.y); } int cross(point p0,point p1,point p2){ //大于0, 逆时针 return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } void convex(int n){ sort(pt,pt+n,cmp); cnt=0; int top=0; sta[top++]=0; sta[top++]=1; //下凸包 for(int i=2;i<n;i++){ while(top>1&&cross(pt[sta[top-2]],pt[sta[top-1]],pt[i])<=0) { top--; } sta[top++]=i; } for(int i=0;i<top;i++) ans[cnt++]=sta[i]; top=0; sta[top++]=n-1; sta[top++]=n-2; //求上凸包 (将pt[n-1]和pt[0]连接起来。) for(int i=n-3;i>=0;i--){ while(top>1&&cross(pt[sta[top-2]],pt[sta[top-1]],pt[i])<=0){ top--; } sta[top++]=i; } for(int i=0;i<top;i++) ans[cnt++]=sta[i]; } int main() { //freopen("cin.txt","r",stdin); int n,l,t; double Pi=acos(0.0)*2; cin>>t; while(t--){ scanf("%d%d",&n,&l); for(int i=0;i<n;i++){ scanf("%d%d",&pt[i].x,&pt[i].y); } convex(n); double res=2*Pi*l; for(int i=0;i<cnt-1;i++){ res+=sqrt(1.0*(pt[ans[i]].x-pt[ans[i+1]].x)*(pt[ans[i]].x-pt[ans[i+1]].x) +(pt[ans[i]].y-pt[ans[i+1]].y)*(pt[ans[i]].y-pt[ans[i+1]].y)); } printf("%.0lf\n",res); if(t) puts(""); } return 0; }
#include <iostream> #include <cmath> #include <cstdio> #include <algorithm> using namespace std; struct point{ int x,y; }pt[1005],ans[1005]; int cnt; int cmp(point a,point b){ if(a.x==b.x) return a.y<b.y; //左下角优先 先左再下 return a.x<b.x; } int cross(point p0,point p1,point p2){ //大于0, 逆时针 return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } double length(point a,point b){ return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } void convex(int n){ sort(pt,pt+n,cmp); cnt=0; for(int i=0;i<n;i++){ //下凸包 while(cnt>1&&cross(ans[cnt-2],ans[cnt-1],pt[i])<=0) { cnt--; } ans[cnt++]=pt[i]; } int key=cnt; //求上凸包 (将pt[n-1]和pt[0]连接起来。) for(int i=n-2;i>=0;i--){ while(cnt>key&&cross(ans[cnt-2],ans[cnt-1],pt[i])<=0){ cnt--; } ans[cnt++]=pt[i]; } } int main() { //freopen("cin.txt","r",stdin); int n,l; double Pi=atan(1.0)*4; int t=0; cin>>t; while(t--){ scanf("%d%d",&n,&l); for(int i=0;i<n;i++){ scanf("%d%d",&pt[i].x,&pt[i].y); } convex(n); double res=2*Pi*l; for(int i=0;i<cnt-1;i++){ res+=length(ans[i],ans[i+1]); } printf("%.0lf\n",res); if(t) puts(""); } return 0; }