51 nod: 1298 圆与三角形
2017-12-05 19:37
405 查看
题目
Input
Output
Input示例
Output示例
题解
代码
4-1:三个数,前两个数为圆心的坐标xc, yc,第3个数为圆的半径R。(-3000 <= xc, yc <= 3000, 1 <= R <= 3000)
4-2:2个数,三角形第1个点的坐标。
4-3:2个数,三角形第2个点的坐标。
4-4:2个数,三角形第3个点的坐标。(-3000 <= xi, yi <= 3000)
1. 三个点都在圆内,不相交
2. 三个点都在圆外,需要特殊判断
3. 其它:相交
对于情况2:
1. 如果圆与任意一条边相交,则相交,对于每条边转入2
2. 对于每一条边,求点到直线距离,如果距离大于半径,无交点,否则,转入3
3. 如果以两个三角形点的为中心的角都是锐角,则相交,否则不相交,具体分析如下:
圆心到线段所在直线距离大于r
这种情况下,直接可以确定该线段与圆无交点
圆心到线段所在直线距离小于r
第一种情况:
这种情况下,我们可以得到,∠OAB=∠OCA+∠COA,由于是垂足,因此∠OCA=90∘,∠OAB>90∘。因此得到对应的向量点乘后小于0。注:不需要考虑A是切点,如果是切点,就已经是前面的第3种情况,直接就判断相交。
第二种情况:
这种情况下,可以得到∠OAC+∠AOC=90∘,因此∠OAC<90∘。同理分析∠OBC。因此这两个角都必须是锐角,即向量点乘后大于0。
直线方程
直线方程的标准式是:Ax+By+C=0。需要对垂直和水平的直线进行特殊的考虑。点到直线的距离的公式是:
|Ax+By+C|A2+B2−−−−−−−√
思路参考自 http://blog.csdn.net/f_zyj/article/details/52066901
Input
Output
Input示例
Output示例
题解
代码
题目
给出圆的圆心和半径,以及三角形的三个顶点,问圆同三角形是否相交。相交输出”Yes”,否则输出”No”。(三角形的面积大于0)。Input
第1行:一个数T,表示输入的测试数量(1 <= T <= 10000),之后每4行用来描述一组测试数据。4-1:三个数,前两个数为圆心的坐标xc, yc,第3个数为圆的半径R。(-3000 <= xc, yc <= 3000, 1 <= R <= 3000)
4-2:2个数,三角形第1个点的坐标。
4-3:2个数,三角形第2个点的坐标。
4-4:2个数,三角形第3个点的坐标。(-3000 <= xi, yi <= 3000)
Output
共T行,对于每组输入数据,相交输出”Yes”,否则输出”No”。Input示例
2 0 0 10 10 0 15 0 15 5 0 0 10 0 0 5 0 5 5
Output示例
Yes No
题解
判断一个圆是否与三角形相交,先对点的分布进行如下的判断:1. 三个点都在圆内,不相交
2. 三个点都在圆外,需要特殊判断
3. 其它:相交
对于情况2:
1. 如果圆与任意一条边相交,则相交,对于每条边转入2
2. 对于每一条边,求点到直线距离,如果距离大于半径,无交点,否则,转入3
3. 如果以两个三角形点的为中心的角都是锐角,则相交,否则不相交,具体分析如下:
圆心到线段所在直线距离大于r
这种情况下,直接可以确定该线段与圆无交点
圆心到线段所在直线距离小于r
第一种情况:
这种情况下,我们可以得到,∠OAB=∠OCA+∠COA,由于是垂足,因此∠OCA=90∘,∠OAB>90∘。因此得到对应的向量点乘后小于0。注:不需要考虑A是切点,如果是切点,就已经是前面的第3种情况,直接就判断相交。
第二种情况:
这种情况下,可以得到∠OAC+∠AOC=90∘,因此∠OAC<90∘。同理分析∠OBC。因此这两个角都必须是锐角,即向量点乘后大于0。
直线方程
直线方程的标准式是:Ax+By+C=0。需要对垂直和水平的直线进行特殊的考虑。点到直线的距离的公式是:
|Ax+By+C|A2+B2−−−−−−−√
代码
#include <iostream> #include <limits> #include <algorithm> using namespace std; using ll = long long; ll Distance(ll x1, ll y1, ll x2, ll y2) { return (x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2); } bool isSegmentCircle(ll x, ll y, ll r,ll px1, ll py1, ll px2, ll py2) { ll a, b, c; // 直线方程的三个参数 if (px1 == px2) { a = 1; b = 0; c = -px1; } else if (py1 == py2) { a = 0; b = 1; c = -py1; } else { a = py2 - py1; b = px1 - px2; c = px2*py1 - px1*py2; } ll dMax = r*r*(a*a + b*b); ll dUp = a*x + b*y + c; dUp = dUp*dUp; // 点到直线距离 if (dUp > dMax) return false; // 向量点乘 ll sita1 = (x - px1)*(px2 - px1) + (y - py1)*(py2 - py1); ll sita2 = (x - px2)*(px1 - px2) + (y - py2)*(py1 - py2); if (sita1 > 0 && sita2 > 0) return true; return false; } bool isInterset(ll x, ll y, ll r, ll posX[], ll posY[]) { ll d1 = Distance(x, y, posX[0], posY[0]); ll d2 = Distance(x, y, posX[1], posY[1]); ll d3 = Distance(x, y, posX[2], posY[2]); ll d = r*r; if (d1 < d && d2 < d && d3 < d) return false; if (d1 > d && d2 > d && d3>d) { bool f = false; f = f || isSegmentCircle(x, y,r, posX[0], posY[0], posX[1], posY[1]); f = f || isSegmentCircle(x, y,r, posX[1], posY[1], posX[2], posY[2]); f = f || isSegmentCircle(x, y,r, posX[2], posY[2], posX[0], posY[0]); return f; } return true; } int main() { // freopen("input.txt", "r", stdin); int T; cin >> T; ll x, y, r; ll posX[3]; ll posY[3]; while (T--) { scanf("%lld%lld%lld", &x, &y, &r); for (int i = 0; i < 3; ++i) scanf("%lld%lld", &posX[i], &posY[i]); if (isInterset(x, y, r, posX, posY)) cout << "Yes\n"; else cout << "No\n"; } return 0; }
思路参考自 http://blog.csdn.net/f_zyj/article/details/52066901
相关文章推荐
- 51 nod 1298 圆与三角形 【计算几何】
- 51 nod 1298(计算几何)@
- 51 nod 乘法逆元
- 51nod 1298 圆与三角形 (计算几何)
- 51 nod 1212 基础MST
- 51 nod 1267 4个数和为0
- 51 Nod 1791 合法括号子段【分治+字符串】
- 两个数的平方和 51Nod - 1080
- 51 nod 1242 斐波那契数列的第N项 矩阵快速幂
- 51 nod 1500 苹果曼和树(树形DP)
- 51 nod 1087 1 10 100 1000 (set)
- 1126 求递推序列的第N项(51nod)
- 51 nod 1804 小C的多边形(贪心)
- [数学杂题]51 Nod 1765——谷歌的恐龙
- 51 nod 1310 Chandrima and XOR(规律)
- 51 nod 1181 质数中的质数(质数筛法)
- [树状数组]51 Nod 1711——平均数
- [51NOD](1003)阶乘后面0的数量 ---数学
- 51nod多重背包问题
- 51 NOD 1685 第K大区间2 二分+BIT