HDU4404 Worms



http://acm.hdu.edu.cn/showproblem.php?pid=4404


2012jinhua online


求圆与多边形相交的面积。


模板题。


#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
//#include <vector>
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
//const double eps=1e-7;
//const double INF=1e50;
//const double pi=acos(-1);

const int maxn = 105;
#define pi  acos(-1.0)

struct point1{
    double x, y ;
    point1(){}
    point1(double x, double y):x(x),y(y){}
    double operator *(const point1 &b)const{
        return x * b.y - y * b.x;
    }
    point1 operator -(const point1 &b)const{
        return point1( x - b.x, y - b.y );
    }
    void in(){
         scanf("%lf%lf",&x,&y);
    }
}p[maxn] , q[maxn], o;

const double eps = 1e-10;
inline double max (double a, double b) { if (a > b) return a; else return b; }
inline double min (double a, double b) { if (a < b) return a; else return b; }
inline int fi (double a)
{
    if (a > eps) return 1;
    else if (a >= -eps) return 0;
    else return -1;
}
class vector
{
public:
    double x, y;
    vector (void) {}
    vector (double x0, double y0) : x(x0), y(y0) {}
    double operator * (const vector& a) const { return x * a.y - y * a.x; }
    double operator % (const vector& a) const { return x * a.x + y * a.y; }
    vector verti (void) const { return vector(-y, x); }
    double length (void) const { return sqrt(x * x + y * y); }
    vector adjust (double len)
    {
        double ol = len / length();
        return vector(x * ol, y * ol);
    }
    vector oppose (void) { return vector(-x, -y); }
};
class point
{
public:
    double x, y;
    point (void) {}
    point (double x0, double y0) : x(x0), y(y0) {}
    vector operator - (const point& a) const { return vector(x - a.x, y - a.y); }
    point operator + (const vector& a) const { return point(x + a.x, y + a.y); }
};
class segment
{
public:
    point a, b;
    segment (void) {}
    segment (point a0, point b0) : a(a0), b(b0) {}
    point intersect (const segment& s) const
    {
        vector v1 = s.a - a, v2 = s.b - a, v3 = s.b - b, v4 = s.a - b;
        double s1 = v1 * v2, s2 = v3 * v4;
        double se = s1 + s2;
        s1 /= se, s2 /= se;
        return point(a.x * s2 + b.x * s1, a.y * s2 + b.y * s1);
    }
    point pverti (const point& p) const
    {
        vector t = (b - a).verti();
        segment uv(p, p + t);
        return intersect(uv);
    }
    bool on_segment (const point& p) const
    {
        if (fi(min(a.x, b.x) - p.x) <= 0 && fi(p.x - max(a.x, b.x)) <= 0 &&
            fi(min(a.y, b.y) - p.y) <= 0 && fi(p.y - max(a.y, b.y)) <= 0) return true;
        else return false;
    }
};
double radius;
point polygon[550];
double kuras_area (point a, point b)
{
    point ori(0, 0);
    int sgn = fi((b - ori) * (a - ori));
    double da = (a - ori).length(), db = (b - ori).length();
    int ra = fi(da - radius), rb = fi(db - radius);
    double angle = acos(((b - ori) % (a - ori)) / (da * db));
    segment t(a, b); point h, u; vector seg;
    double ans, dlt, mov, tangle;

    if (fi(da) == 0 || fi(db) == 0) return 0;
    else if (sgn == 0) return 0;
    else if (ra <= 0 && rb <= 0) return fabs((b - ori) * (a - ori)) / 2 * sgn;
    else if (ra >= 0 && rb >= 0)
    {
        h = t.pverti(ori);
        dlt = (h - ori).length();
        if (!t.on_segment(h) || fi(dlt - radius) >= 0)
            return radius * radius * (angle / 2) * sgn;
        else
        {
            ans = radius * radius * (angle / 2);
            tangle = acos(dlt / radius);
            ans -= radius * radius * tangle;
            ans += radius * sin(tangle) * dlt;
            return ans * sgn;
        }
    }
    else
    {
        h = t.pverti(ori);
        dlt = (h - ori).length();
        seg = b - a;
        mov = sqrt(radius * radius - dlt * dlt);
        seg = seg.adjust(mov);
        if (t.on_segment(h + seg)) u = h + seg;
        else u = h + seg.oppose();
        if (ra == 1) swap(a, b);
        ans = fabs((a - ori) * (u - ori)) / 2;
        tangle = acos(((u - ori) % (b - ori)) / ((u - ori).length() * (b - ori).length()));
        ans += radius * radius * (tangle / 2);
        return ans * sgn;
    }
}

int main()
{
    //freopen("a","r",stdin);

    int n, i;
    double v0,thi,time1,g,r;

    while(1)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf",&o.x,&o.y,&v0,&thi,&time1,&g,&radius);
        if (fabs(o.x)<eps && fabs(o.y)<eps && fabs(v0)<eps &&  fabs(thi)<eps && fabs(time1)<eps && fabs(g)<eps && fabs(radius)<eps) break;
        thi=thi*acos(-1)/180.00;
        o.x += v0*cos(thi)*time1 , o.y += v0*sin(thi)*time1-0.5*g*time1*time1 ;

       // cout<<o.x<<' '<<o.y<<' '<<r<<endl;

        double x,y;
        scanf("%d",&n);
        for (i = 0; i < n; i++)
        {
            scanf("%lf %lf", &x, &y);
            x-=o.x;
            y-=o.y;
            polygon[i] = point(x, y);
        }
        double area = 0;
        for (int i = 0; i < n; i++)
            area += kuras_area(polygon[i], polygon[(i + 1) % n]);
        printf("%.2f\n", fabs(area));

    }

    return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
//#include <vector>
#include <iostream>
#include <algorithm>
#include<string>
using namespace std;
//const double eps=1e-7;
//const double INF=1e50;
//const double pi=acos(-1);

const int maxn = 105;
#define pi  acos(-1.0)
#define eps 1e-7
// poj 3675 一个圆和一个多边形的面积交的大
double sign( double x ){
    if( x < -eps ) return -1;
    return x > eps;
}

struct point{
    double x, y ;
    point(){}
    point(double x, double y):x(x),y(y){}
    double operator *(const point &b)const{
        return x * b.y - y * b.x;
    }
    point operator -(const point &b)const{
        return point( x - b.x, y - b.y );
    }
    void in(){
         scanf("%lf%lf",&x,&y);
    }
}p[maxn] , q[maxn], o,p0;
double r ,ans ; // 已原点为圆心的圆半径
double thi,time1,g,v0;

圆o与线段x-y的交点,,如果存在顺序存入p[0]和p[1],,返回交点的个数
int xianduan_jiao_yuan( point o, double r,point u, point v, point &o1, point &o2){
    u = u - o;  v = v - o;
    point  w = v - u ;
    double a = w.x * w.x + w.y * w.y ;
    double b = w.x * u.x * 2 + w.y * u.y * 2;
    double c = u.x * u.x + u.y * u.y - r * r;
    double d = b * b - 4 * a * c;
    if( sign( d ) < 0) return 0;
    d = sqrt( d );
    double t1 = ( - b + d )/2/a, t2 = ( - b - d )/2/a;
    if( t1 > t2 )  swap( t1, t2 );
    int ans = 0;
    注意这里端点在圆上没有算作相交,有需要改成等号既可
    if( sign( t1 ) > 0 && sign( t1 - 1 ) < 0 ){
        ans ++ ;
        o1 = point( u.x + w.x * t1 + o.x, u.y + w.y*t1+o.y);
    }注意重根这里算作了一个交点,,
    if(sign( t1 - t2) != 0 && sign(t2)>0&&sign(t2-1)<0){
        ans ++;
        if( ans == 1 ) o1 = point( u.x+w.x*t2+o.x,u.y+w.y*t2+o.y );
        else o2 = point( u.x+w.x*t2+o.x,u.y+w.y*t2+o.y );
    }
    return ans ;
}

double get( point p[], int n ){
     double ans = 0;
     for( int i = 1; i < n; i ++ ){
          point a, b;
          a = p[ i - 1]; b = p[ i ];//只要有一个人在圆外面 那就只需要计算扇形的面积即可
          if( sqrt(a.x*a.x+a.y*a.y) - r > eps || sqrt( b.x * b.x + b.y*b.y) - r > eps ){
              double t = atan2(b.y , b.x ) - atan2(a.y , a.x ) ;
              while( t - pi > eps  ) t -= pi * 2 ;//t的范围是( -pi , pi )
              while( t + pi < -eps ) t += pi * 2 ;
              ans += t * r * r ;
          }else ans += a * b ;  //叉乘  这个在圆里面
     }
     return ans ;
}

void add( point a , point b ){
     point p1, p2;
     int end = 0;
     p[end++] = a;
     point o1, o2;
     int t = xianduan_jiao_yuan(point(0,0),r,a,b,o1,o2);
     if( t >= 1) p[end++] = o1;
     if( t >= 2) p[end++] = o2;
     p[end++] = b;
     ans += get( p, end );
}

int main()
{
    //freopen("a","r",stdin);

    int n, i;
    double v0,thi,time1,g;

    while(1)
    {
        scanf("%lf%lf%lf%lf%lf%lf%lf",&o.x,&o.y,&v0,&thi,&time1,&g,&r);
        if (fabs(o.x)<eps && fabs(o.y)<eps && fabs(v0)<eps &&  fabs(thi)<eps && fabs(time1)<eps && fabs(g)<eps && fabs(r)<eps) break;
        thi=thi*acos(-1)/180.00;
        o.x += v0*cos(thi)*time1 , o.y += v0*sin(thi)*time1-0.5*g*time1*time1 ;
        ans=0;

        scanf("%d",&n);
        for(  i = 0; i < n; i ++ ){
            scanf("%lf%lf",&q[i].x, &q[i].y );
            q[i] = q[i] - o;
        }
        q[n] = q[0];
        for( i  =0; i < n; i++ ){
            add( q[i], q[i+1] );
        }
        printf("%.2lf\n",fabs(ans)/2);
    }

    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值