hdu 4404 Worms

本文介绍了一种计算三角形与圆相交的有效面积的方法,并提供了完整的C++代码实现。通过将圆与三角形的交点分为0、1、2个交点的情况进行分类讨论,利用向量和几何原理来解决该问题。适用于解决计算几何中的相关问题。
摘要由CSDN通过智能技术生成

http://hi.baidu.com/billdu/item/703ad4e15d819db52f140b0b 根据这个思路写的。

将圆与三角形的交按照0、1、2个交点分类

然后就好做多啦,有效面积是个强大的工具

买一送2,poj 3675,2986一样可以用模板过掉。

咔咔。有自己的模板真好~~

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define FORD(i,s,t) for(int i=(s-1); i>=t; i--)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

using namespace std;

const int MAX = 110;
const double pi = acos(-1.0);
struct point {
	double x, y;
};
point p[MAX];
point c;
double r;
const double eps = 1e-8;
int dcmp(double x) {
	return x < -eps ? -1 : x > eps ? 1 : 0;
}
double disp2p(point a,point b) //  a b 两点之间的距离 
{
	return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 顺时针是正 
{
	return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
point l2l_inst_p(point u1,point u2,point v1,point v2)
{
	point ans = u1;
	double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/
				((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));
	ans.x += (u2.x - u1.x)*t;
	ans.y += (u2.y - u1.y)*t;
	return ans;
}
//直线与圆的交点 
int l2c_inst_p(point c,double r,point l1,point l2,point *pv)
{
	int cnt = 0;
	double d = fabs( crossProduct(c,l1,l2) )/disp2p(l1,l2);
	if( dcmp(d-r) > 0 )
		return 0;
	point p = c;
	double t;
	p.x += l1.y - l2.y;
	p.y += l2.x - l1.x;
	p = l2l_inst_p(p,c,l1,l2);
	t = sqrt(r*r - disp2p(p,c)*disp2p(p,c))/disp2p(l1,l2);
	pv[cnt].x = p.x + (l2.x - l1.x)*t;
	pv[cnt++].y = p.y + (l2.y - l1.y)*t;
	if( dcmp(d-r) == 0 )
		return cnt;
	pv[cnt].x = p.x - (l2.x - l1.x)*t;
	pv[cnt++].y = p.y - (l2.y - l1.y)*t;
	return cnt;
}
//若不包括端点,将等于号去掉 
bool onSegment(point a, point b, point c)
{
	//和端点重合 
	if( dcmp(c.x - a.x) == 0 && dcmp(c.y - a.y) == 0 || dcmp(c.x - b.x) == 0 && dcmp(c.y - b.y) == 0 )
		return false; 
	if( dcmp(crossProduct(a,b,c)) == 0 && dcmp(c.x - min(a.x,b.x)) >= 0 && 
		dcmp(c.x-max(a.x,b.x)) <= 0 && dcmp(c.y - min(a.y,b.y)) >= 0 && dcmp(c.y-max(a.y,b.y)) <= 0 )
		return true;
	return false;
}
//求线段与圆的交点,p中存放交点,返回交点个数 
//若不包括端点,需要在onSegment函数中控制一下 
int seg2c_inst_p(point c,double r,point l1,point l2,point *p)
{
	point pv[3];
	int cnt = l2c_inst_p(c, r, l1, l2, pv);
	int cntp = 0;
	FOR(i, 0, cnt)
		if( onSegment(l1, l2, pv[i]) )
			p[cntp++] = pv[i];
	//按照交点离l1的顺序从小到大排序 
	if(	cntp == 2 ) {
		if(disp2p(p[0], l1) > disp2p(p[1], l1) )
			swap(p[0], p[1]);
	}
	return cntp;
}
double area_triangle(point a,point b,point c)
{
	return fabs( crossProduct(a,b,c) )/2.0;
}
//求以acb为圆心角的扇形(小于180度) 
double area_shan(point a, point b, point c, double r) {
	double aa = disp2p(c, b);
	double bb = disp2p(a, c);
	double cc = disp2p(a, b);
	double ang = acos((aa*aa + bb*bb - cc*cc)/(2*aa*bb));
	return ang/2*r*r;
}
//三角形与圆的交面积,其中c是圆心 
double area_triangle2circle(point a, point b, point c, double r) {
	point p[3];
	int cnt = seg2c_inst_p(c, r, a, b, p);
	if( dcmp(crossProduct(a, b, c)) == 0 ) 
		return 0;
	if( cnt == 0 ) {
		if( dcmp(disp2p(a, c) - r) <= 0 && dcmp(disp2p(b, c) - r) <= 0 )
			return area_triangle(a, b, c);
		else
			return area_shan(a, b, c, r); 
	}
	if( cnt == 1 ) {
		if( dcmp(disp2p(a, c) - r) > 0 && dcmp(disp2p(b, c) - r) > 0 )
			return area_shan(a, b, c, r);
		if( dcmp(disp2p(a, c) - r) > 0 ) 
			swap(a, b);
		return area_shan(p[0], b, c, r) + area_triangle(a, p[0], c);
	}
	if( cnt == 2 ) {
		return area_shan(a, p[0], c, r) + area_shan(p[1], b, c, r)
				+ area_triangle(p[0], p[1], c);
	}
}
double solve(int n) {
	double area = 0;
	FOR(i, 0, n) {
		area += area_triangle2circle(p[i], p[(i+1)%n], c, r) *
				 dcmp(crossProduct(c, p[(i+1)%n], p[i]));
	}
	return fabs(area);
}
void cal(double x0,double y0,double v0,double a,double t,double g)
{
    double yt = v0*sin(a);
    double xt = v0*cos(a);
    double xx = x0 + xt*t;
    double yy = y0 + yt*t-0.5*g*t*t;
    c.x = xx;
    c.y = yy;
}
int main() {
	
	int n;
	double x, y, v, ang, t, g;
	
	while( ~scanf("%lf%lf%lf%lf%lf%lf%lf", &x, &y, &v, &ang, &t, &g, &r) ) {
		if( x == y && y == v && v == ang && ang == t && t == g && g == r && r == 0 )
			break;
		scanf("%d", &n);
		FOR(i, 0, n)
			scanf("%lf%lf", &p[i].x, &p[i].y);
		cal(x, y, v, ang/180*pi, t, g);
		double ans = solve(n);
		printf("%.2lf\n", ans);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值