第一次OJ的总结

2018/10/6

鸽了许久,但还是要做一下总结。

第一次OJ要求如下

问题描述:

给定二维平面上的一个圆和一个三角形,视两者为两个点集C和T。C和T均不包含图形的内部,仅包含图形的边界。判断集合C和T的交集是否非空。

输入格式:

(第一行)正整数N,代表接下来有N组测试数据。
(接下来的N行,每一行格式是:)r x0 y0 x1 y1 x2 y2 x3 y3 (解释:r为圆半径,(x0, y0)为圆心坐标,(x1,y1), (x2,y2), (x3,y3)为三角形3个顶点坐标)

数据范围:

0<N<1,000,000

横、纵坐标属于区间[-1000, 1000]

输出格式:

扫描二维码关注公众号,回复: 3535634 查看本文章

一共N行,每行输出数字0或1。若C和T交集非空,输出1;若C和T交集为空集,输出0.

输入样例:

2
1 0 0 5 5 6 6 7 4
1 0 0 0 2 1 -1 2 1

输出样例:

0
1

简而言之就是判断圆和三角形有无交点。

我们分类讨论:

    1.三角形的三个顶点都在圆内,不可能相交;

    2. 三角形的三个顶点都在圆外,需要另外讨论;

    3.其余情况,此时一定相交。

接下来对都在圆外的情况继续加以讨论。分别三条边与圆的相交关系,需要注意的是,现在三条边的端点都在圆外。

只需研究其中一条边,其他边类似。首先还是计算这条边到圆心的垂直距离,如果大于半径的话,一定不相交。如果小于或等于半径的话,就要判断垂足是否在边上,这里可以转为计算角度或者说余弦值,如果圆心与两端点所连成的角都是锐角,即余弦值都为正,那么相交。否则不相交(由于不可能出现相切的情况,故余弦值不会为零)。

余弦值可由向量公式得到,转化为坐标形式即可,需要注意的是,这里只需要正负,所以可以将分母抛弃。

值得一提的是,写OJ时,网站提醒我cin和cout并非就比scanf和printf慢,只需加上:

ios::sync_with_stdio(false);

如果前面没有写using namespace std 的话加上std::,这是为了解除C++对C做的兼容,但是之后不能再使用scanf和printf了(using namespace std有时会带来麻烦,只可以在源文件中写写,避免在头文件中使用)。

具体代码如下:

#include <iostream>
#include <math.h>
using namespace std;

struct Point{
	double x;
	double y;
};

inline double dist(const Point &a,const Point &b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

inline double angle(const Point &a,const Point &b,const Point &c){
	return ((a.x-b.x)*(c.x-b.x)+(a.y-b.y)*(c.y-b.y));
}

bool crline(double R,const Point &a,const Point &b,const Point &c){
	double height = abs((b.y-c.y)*a.x+(c.x-b.x)*a.y+b.x*c.y-c.x*b.y)/sqrt((b.x-c.x)*(b.x-c.x)+(b.y-c.y)*(b.y-c.y));
	if(height>R)
		return 0;
	else if(height == R)
		return 1;
	else if(angle(a,b,c)<0 || angle(a,c,b)<0)
		return 0;
	else
		return 1;
}

int main(){
	ios::sync_with_stdio(false);
	unsigned int i,j;
	unsigned int num;
	double r;
	Point point[4];
	cin>>num;
	bool *ans = new bool[num];
	for(i=0;i<num;++i){
		cin>>r;
			for(j=0;j<4;++j){
				cin>>point[j].x>>point[j].y;
			}
    
	double len1,len2,len3;
	len1 = dist(point[0],point[1]);
	len2 = dist(point[0],point[2]);
	len3 = dist(point[0],point[3]);

	if(len1>r && len2>r && len3>r){
		if(crline(r,point[0],point[1],point[2]) || crline(r,point[0],point[1],point[3]) || crline(r,point[0],point[2],point[3]))
			ans[i] = 1;
		else ans[i] = 0;
	}
	else if(len1<r && len2<r && len3<r)
		ans[i] = 0;
	else
		ans[i] = 1;
	}
	for(i=0;i<num;++i)
		cout<<ans[i]<<"\n";
	delete []ans;ans = NULL;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41238584/article/details/82949504