题意:给出一些矩形和这些矩形的旋转角度,用一个最小凸多边形,覆盖所有矩形,然后求解矩形在整个凸多边形中所占的比例。
分析:很显然求解凸包,但又一些问题,第一就是旋转角度,本题给是角度制,但c++中提供的三角函数却是弧度值,所以要转换成弧度制,转换方式为 d=2*pi*(j/360);
此外,要用到旋转之后的点的坐标,这之间有个公式:
假设对图片上任意点(x,y),绕一个坐标点(rx0,ry0)逆时针旋转a角度后的新的坐标设为(x0, y0),有公式:
x0= (x - rx0)*cos(a) - (y - ry0)*sin(a) + rx0 ;
y0= (x - rx0)*sin(a) + (y - ry0)*cos(a) + ry0 ;
本题还是顺时针旋转的,所以要用2*pi减去这个角度。
代码如下:
<span style="font-family:FangSong_GB2312;font-size:18px;">#include <map> #include <set> #include <vector> #include <math.h> #include <string> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <functional> using namespace std; const int MAXN=100005; const double eps=1e-10; const double pi=acos(-1.0); //圆周率pi int dcmp(double x){ if(fabs(x)<eps)return 0; if(x>0)return 1; return -1; } struct Point { double x,y; int id; }p[MAXN]; Point Sub(Point a,Point b){ Point ans; ans.x=a.x-b.x; ans.y=a.y-b.y; return ans; } double dot(Point a,Point b,Point c){ double s1=b.x-a.x; double t1=b.y-a.y; double s2=c.x-a.x; double t2=c.y-a.y; return s1*s2+t1*t2; } int n,res[MAXN],top; double Cross(Point a,Point b){ return a.x*b.y-a.y*b.x; } bool cmp(Point a,Point b){ if(a.y==b.y)return a.x<b.x; return a.y<b.y; } bool mult(Point sp,Point ep,Point op){ return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y); } void Graham(){ int len; top=1; sort(p,p+n,cmp); if(n==0)return;res[0]=0; if(n==1)return;res[1]=1; if(n==2)return;res[2]=2; for(int i=2;i<n;i++){ while(top&&mult(p[i],p[res[top]],p[res[top-1]]))top--; res[++top]=i; } len=top; res[++top]=n-2; for(int i=n-3;i>=0;i--){ while(top!=len&&mult(p[i],p[res[top]],p[res[top-1]]))top--; res[++top]=i; } }//求解凸包 double dis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double Poly_are(){ double ans=0; for(int i=1;i<top-1 ;i++) ans+=Cross(Sub(p[res[i]],p[res[0]]),Sub(p[res[i+1]],p[res[0]])); return fabs(ans)/2.0; }//求解凸多边形的面积 int main() { int t; scanf("%d",&t); while(t--){ double x,y,w,h,j; int k; n=0; double ans=0; scanf("%d",&k); while(k--){ scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j); j=2*pi*(j/360.0); j=2*pi-j; ans+=w*h; double xx[10],yy[10]; xx[1]=x-w/2; xx[2]=x-w/2; xx[3]=x+w/2; xx[4]=x+w/2; yy[1]=y-h/2; yy[2]=y+h/2; yy[3]=y-h/2; yy[4]=y+h/2; double sum1,sum2; for(int i=1;i<=4;i++){ sum1=(xx[i]-x)*cos(j)-(yy[i]-y)*sin(j)+x; sum2=(yy[i]-y)*cos(j)+(xx[i]-x)*sin(j)+y; //找出旋转后的点 p[n].x=sum1; p[n++].y=sum2; } } Graham(); double sum=Poly_are(); double tmp=(ans*100/sum);//直接除旧行 printf("%.1f ",tmp); puts("%");//%不是很会输出,所以用这种方法了 } return 0; }</span>
题意:给出一些矩形和这些矩形的旋转角度,用一个最小凸多边形,覆盖所有矩形,然后求解矩形在整个凸多边形中所占的比例。
分析:很显然求解凸包,但又一些问题,第一就是旋转角度,本题给是角度制,但c++中提供的三角函数却是弧度值,所以要转换成弧度制,转换方式为 d=2*pi*(j/360);
此外,要用到旋转之后的点的坐标,这之间有个公式:
假设对图片上任意点(x,y),绕一个坐标点(rx0,ry0)逆时针旋转a角度后的新的坐标设为(x0, y0),有公式:
x0= (x - rx0)*cos(a) - (y - ry0)*sin(a) + rx0 ;
y0= (x - rx0)*sin(a) + (y - ry0)*cos(a) + ry0 ;
本题还是顺时针旋转的,所以要用2*pi减去这个角度。
代码如下:
<span style="font-family:FangSong_GB2312;font-size:18px;">#include <map> #include <set> #include <vector> #include <math.h> #include <string> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <functional> using namespace std; const int MAXN=100005; const double eps=1e-10; const double pi=acos(-1.0); //圆周率pi int dcmp(double x){ if(fabs(x)<eps)return 0; if(x>0)return 1; return -1; } struct Point { double x,y; int id; }p[MAXN]; Point Sub(Point a,Point b){ Point ans; ans.x=a.x-b.x; ans.y=a.y-b.y; return ans; } double dot(Point a,Point b,Point c){ double s1=b.x-a.x; double t1=b.y-a.y; double s2=c.x-a.x; double t2=c.y-a.y; return s1*s2+t1*t2; } int n,res[MAXN],top; double Cross(Point a,Point b){ return a.x*b.y-a.y*b.x; } bool cmp(Point a,Point b){ if(a.y==b.y)return a.x<b.x; return a.y<b.y; } bool mult(Point sp,Point ep,Point op){ return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y); } void Graham(){ int len; top=1; sort(p,p+n,cmp); if(n==0)return;res[0]=0; if(n==1)return;res[1]=1; if(n==2)return;res[2]=2; for(int i=2;i<n;i++){ while(top&&mult(p[i],p[res[top]],p[res[top-1]]))top--; res[++top]=i; } len=top; res[++top]=n-2; for(int i=n-3;i>=0;i--){ while(top!=len&&mult(p[i],p[res[top]],p[res[top-1]]))top--; res[++top]=i; } }//求解凸包 double dis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double Poly_are(){ double ans=0; for(int i=1;i<top-1 ;i++) ans+=Cross(Sub(p[res[i]],p[res[0]]),Sub(p[res[i+1]],p[res[0]])); return fabs(ans)/2.0; }//求解凸多边形的面积 int main() { int t; scanf("%d",&t); while(t--){ double x,y,w,h,j; int k; n=0; double ans=0; scanf("%d",&k); while(k--){ scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j); j=2*pi*(j/360.0); j=2*pi-j; ans+=w*h; double xx[10],yy[10]; xx[1]=x-w/2; xx[2]=x-w/2; xx[3]=x+w/2; xx[4]=x+w/2; yy[1]=y-h/2; yy[2]=y+h/2; yy[3]=y-h/2; yy[4]=y+h/2; double sum1,sum2; for(int i=1;i<=4;i++){ sum1=(xx[i]-x)*cos(j)-(yy[i]-y)*sin(j)+x; sum2=(yy[i]-y)*cos(j)+(xx[i]-x)*sin(j)+y; //找出旋转后的点 p[n].x=sum1; p[n++].y=sum2; } } Graham(); double sum=Poly_are(); double tmp=(ans*100/sum);//直接除旧行 printf("%.1f ",tmp); puts("%");//%不是很会输出,所以用这种方法了 } return 0; }</span>