凸包+多边形重心模板

本模板通过了HDU 3685

凸包模板是正确的,多边形求重心也是正确的,把两块板拼在一起莫名其妙地错了,唉

最后还是调出了,发现有一个函数返回类型本来应该是double,我把它写成int型了,WA了二十多发,醉了醉了。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<queue>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
using namespace std;
const int maxn=1000005,inf=1<<29;
const double eps = 1e-8;
int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};
int n,m,t;
struct P
{
    double x,y;
    P(){}
    P(double x,double y):x(x),y(y){}
    P operator + (P p)
    {
        return P(x+p.x,y+p.y);
    }
    P operator - (P p)
    {
        return P(x-p.x,y-p.y);
    }
    P operator *(double d)
    {
        return P(x*d,y*d);
    }
    double dot(P p)
    {
        return x*p.x+y*p.y;
    }
    double det(P p)
    {
        return x*p.y-y*p.x;
    }
}ps[maxn];//点的坐标存放在这里
struct node{
double x,y,area;
}b[maxn];
bool cmp(P a,P b)
{
    if(a.x!=b.x) return a.x<b.x;
    return a.y<b.y;
}
double area(P a,P b,P c)//求三角形面积
{
    return 0.5*fabs((b-a).det(c-a));
}
double area1(P a,P b,P c)//求三角形有向面积
{
    return 0.5*(b-a).det(c-a);
}
double ploy_area()//求多边形面积
{
    double ans=0.0;
    for(int i=1;i<n-1;i++) ans+=area1(ps[i+1],ps[i],ps[0]);
    return fabs(ans);
}
P Focus( ){//求多边形重心
      double ans_x,ans_y;
      double sum_Area=0;
     int cnt=0;//被切割为三角形的个数
     for( int i=2;i<n;i++ ){
          double tmp=area1( ps[ i-1 ],ps[ i ],ps[ 0 ] );
          b[ cnt ].x=ps[ 0 ].x+ps[ i-1 ].x+ps[ i ].x;
          b[ cnt ].y=ps[ 0 ].y+ps[ i-1 ].y+ps[ i ].y;
         b[ cnt ].area = tmp;
          sum_Area += tmp;
         cnt++;
      }
     ans_x=ans_y=0;
      for( int i=0;i<cnt;i++ ){
         ans_x+=b[ i ].x*b[ i ].area;
         ans_y+=b[ i ].y*b[ i ].area;
      }
      ans_x/=(3.0*sum_Area);
      ans_y/=(3.0*sum_Area);//重心坐标
    P grav;
     grav.x=ans_x,grav.y=ans_y;
     return grav;//返回重心坐标
  }
vector<P> convex_hull(int n)//求凸包
{
    sort(ps,ps+n,cmp);
    int k=0;
    vector<P> qs(n*2);
    for(int i=0;i<n;i++)
    {
        while(k>1&&(qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
        qs[k++]=ps[i];
    }
    for(int i=n-2,t=k;i>=0;i--)
    {
        while(k>t&&(qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])<=0) k--;
        qs[k++]=ps[i];
    }
    qs.resize(k-1);
    return qs;
}
double dist(P a,P b)//求两个点之间的距离的平方
{
    //return (p-q).dot(p-q);
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double dist1(P p,P q)//求两个点之间距离
{
    int t=(p-q).dot(p-q);
    return sqrt(t*1.0);
}
bool judge( P a,P b,P now ){//判断会不会出现钝角
    double dis1,dis2,dis3;
   dis1 = dist( a,b );
    dis2 = dist( a,now );
    dis3 = dist( b,now );
     if( (dis1+dis2-dis3>eps)&&(dis1+dis3-dis2>eps) )
         return true;//这两个角必须为锐角,才可能保证 now 这个点在a,b“之间“
     return false;
 }
void solve()
{
    double x,y;
    P center=Focus();//求出重心
    vector<P> qs=convex_hull(n);//求凸包
   //qs.push_back(qs[0]);
    int cnt=0;
    for(int i=1;i<qs.size();i++)
        if(judge(qs[i-1],qs[i],center)) cnt++;
    if(judge(qs[qs.size()-1],qs[0],center)) cnt++;
    printf("%d\n",cnt);
    //printf("%.2lf %.2lf\n",center.x,center.y);
}
int main()
{
   //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%lf%lf",&ps[i].x,&ps[i].y);
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值