UVA10652【凸包计算】
2016-03-23 11:44
323 查看
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1593
给一些矩形(给定中心(x,y)长w宽h,和旋转角j)
求一个最小多边形把所有的矩形包围,输出矩形所占多边形的面积比。
可以想到是把矩形拆成4个点然后跑凸包。
由于第一次做凸包不是很会,然后看了模板YY一下,就是sort之后每次当前点在凸包最末的那一条边的左边,才能加进来,否则弹掉最后一个点,直到可以加入。
这里还有矩形是旋转的,所以搞点的时候卡了一阵子。
可以看成是每个端点先相对于中心点作原点的向量旋转theta角度之后,把原点平移。
(然而我以为三角函数传入的是360°的角度,没想到竟然是弧度,然后就WA了- -||)
然后处理一下点,就当成裸的凸包吧:
.#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
#define eps 1e-10
const int maxn=620;
const double pi=3.1415926;
using namespace std;
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
else return x<0?-1:1;
}
struct point
{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;
y=_y;
}
point operator +(const point &b)
{
return point(x+b.x,y+b.y);
}
point operator -(const point &b)
{
return point(x-b.x,y-b.y);
}
point operator *(const double &b)
{
return point(x*b,y*b);
}
}p[4*maxn];
double cross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
double dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
int n;
int cnt;
point rotate(point a,double rad)
{
//cout<<a.x*cos(rad)<<" "<<a.y*sin(rad)<<" "<<endl;
return point(a.x*cos(rad)+a.y*sin(rad),a.y*cos(rad)-a.x*sin(rad));
}
bool cmp(point x,point y)
{
if(x.x!=y.x)return x.x<y.x;
else return x.y<y.y;
}
point q[4*maxn];
double ans1,ans2;
void solve()
{
sort(p+1,p+cnt+1,cmp);
int m=0;
for(int i=1;i<=cnt;i++)
{
while(m>1&&dcmp(cross(q[m-1]-q[m-2],p[i]-q[m-2]))<=0)m--;
q[m++]=p[i];
}
int k=m;
for(int i=cnt-1;i>=1;i--)
{
while(m>k&&dcmp(cross(q[m-1]-q[m-2],p[i]-q[m-2]))<=0)m--;
q[m++]=p[i];
}
if(cnt>1)m--;
for(int i=0;i<m-1;i++)ans2+=cross(q[i]-q[0],q[i+1]-q[0]);
ans2=0.5*fabs(ans2);
printf("%.1f %\n",ans1/ans2);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cnt=0;
ans1=ans2=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
double x,y,w,h,j;
scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j);
ans1+=w*h*100;
j=j/180*pi;
//cout<<rotate(point(-w/2,h/2),j).x<<" "<<rotate(point(-w/2,h/2),j).y<<endl;
p[++cnt]=rotate(point(-w/2,h/2),j)+point(x,y);
p[++cnt]=rotate(point(w/2,h/2),j)+point(x,y);
p[++cnt]=rotate(point(-w/2,-h/2),j)+point(x,y);
p[++cnt]=rotate(point(w/2,-h/2),j)+point(x,y);
}
solve();
}
return 0;
}
给一些矩形(给定中心(x,y)长w宽h,和旋转角j)
求一个最小多边形把所有的矩形包围,输出矩形所占多边形的面积比。
可以想到是把矩形拆成4个点然后跑凸包。
由于第一次做凸包不是很会,然后看了模板YY一下,就是sort之后每次当前点在凸包最末的那一条边的左边,才能加进来,否则弹掉最后一个点,直到可以加入。
这里还有矩形是旋转的,所以搞点的时候卡了一阵子。
可以看成是每个端点先相对于中心点作原点的向量旋转theta角度之后,把原点平移。
(然而我以为三角函数传入的是360°的角度,没想到竟然是弧度,然后就WA了- -||)
然后处理一下点,就当成裸的凸包吧:
.#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<cmath>
#define eps 1e-10
const int maxn=620;
const double pi=3.1415926;
using namespace std;
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
else return x<0?-1:1;
}
struct point
{
double x,y;
point(){}
point(double _x,double _y)
{
x=_x;
y=_y;
}
point operator +(const point &b)
{
return point(x+b.x,y+b.y);
}
point operator -(const point &b)
{
return point(x-b.x,y-b.y);
}
point operator *(const double &b)
{
return point(x*b,y*b);
}
}p[4*maxn];
double cross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
double dot(point a,point b)
{
return a.x*b.x+a.y*b.y;
}
int n;
int cnt;
point rotate(point a,double rad)
{
//cout<<a.x*cos(rad)<<" "<<a.y*sin(rad)<<" "<<endl;
return point(a.x*cos(rad)+a.y*sin(rad),a.y*cos(rad)-a.x*sin(rad));
}
bool cmp(point x,point y)
{
if(x.x!=y.x)return x.x<y.x;
else return x.y<y.y;
}
point q[4*maxn];
double ans1,ans2;
void solve()
{
sort(p+1,p+cnt+1,cmp);
int m=0;
for(int i=1;i<=cnt;i++)
{
while(m>1&&dcmp(cross(q[m-1]-q[m-2],p[i]-q[m-2]))<=0)m--;
q[m++]=p[i];
}
int k=m;
for(int i=cnt-1;i>=1;i--)
{
while(m>k&&dcmp(cross(q[m-1]-q[m-2],p[i]-q[m-2]))<=0)m--;
q[m++]=p[i];
}
if(cnt>1)m--;
for(int i=0;i<m-1;i++)ans2+=cross(q[i]-q[0],q[i+1]-q[0]);
ans2=0.5*fabs(ans2);
printf("%.1f %\n",ans1/ans2);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cnt=0;
ans1=ans2=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
double x,y,w,h,j;
scanf("%lf%lf%lf%lf%lf",&x,&y,&w,&h,&j);
ans1+=w*h*100;
j=j/180*pi;
//cout<<rotate(point(-w/2,h/2),j).x<<" "<<rotate(point(-w/2,h/2),j).y<<endl;
p[++cnt]=rotate(point(-w/2,h/2),j)+point(x,y);
p[++cnt]=rotate(point(w/2,h/2),j)+point(x,y);
p[++cnt]=rotate(point(-w/2,-h/2),j)+point(x,y);
p[++cnt]=rotate(point(w/2,-h/2),j)+point(x,y);
}
solve();
}
return 0;
}
相关文章推荐
- 总结一下最近做的计算几何学到的知识
- 1.10055 - Hashmat the brave warrior
- 2.10071 - Back to High School Physics
- 3.458 - The Decoder
- 4.694 - The Collatz Sequence
- 6.494 - Kindergarten Counting Game
- 7.490 - Rotating Sentences
- 8.414 - Machined Surfaces
- 9.488 - Triangle Wave
- A.457 - Linear Cellular Automata
- B.489 - Hangman Judge
- C.445 - Marvelous Mazes
- 1.10494 - If We Were a Child Again
- 2.424 - Integer Inquiry
- 3.10250 - The Other Two Trees
- 5.465 - Overflow
- 6.113 - Power of Cryptography
- 7.10161 - Ant on a Chessboard
- 8.621 - Secret Research
- 9.401 - Palindromes