福大OJ2273(能AC的代码见最后)
根据三角形三点是否在另一个三角形内(如何判断见下图),若全在,则包含。若,有的有的则相交。其余不相交。
这显然是有bug的(见下图),我这样想的,但是能过,可能是测评系统数据太少。
2 2 8 4 -9 6 -8 7 -8 3 4 -7 \
\
\
刚在想如何给点按逆时针排序,然后用向量积判断是否有负值。还可以这样用面积判断
不过很难用精确判断两个浮点数是否相等。
如何判断一个点是否在一个三角形内。
\
其中,判断这个问题最简单的方法是面积法。
\
\
\
如果一个点在三角形内,其与三角形的三个点构成的三个子三角形的面积等于大三角形的面积。否则,大于大三角形的面积。
\
所以,这个问题就转化成如何在知道三角形的三个点的情况下,求这个三角形的面积的问题了。
\
这个问题,比较好理解的方法是使用向量法:先求出这个三角形的对应的平行四边形的面积。然后这个面积的1/2就是三角形的面积了。
\
先随意选择两个点,如B、C通过其坐标相减得向量(B,C)。记得谁减另一个就是指向谁。然后求出其中一个点和剩下一个点的向量。这两个向量的叉乘的便是平行四边形的面积。除以2就是三角形的面积。(注意这里是叉乘 (cross product),而非内积(dot product))
\
\
\
#define _CRTOSECURE_NO_WARNINGS
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const double eps = 1e-5;
struct Node {
double x, y;
Node operator - (const Node B) {
x = x - B.x;
y = y - B.y;
return *this;
}
}node[6];
typedef Node Vector;
double multi(Vector a, Vector b) {
return a.x * b.y - b.x * a.y;
} //矢量积
double area(Node a, Node b, Node c) {
return fabs(multi(b - a, c - a)); //没有乘0.5
}
bool isInner(Node A, Node a, Node b, Node c) { //判断点A是否在三角形abc内
double s = area(a, b, c);
double ss = area(A, a, b) + area(A, a, c) + area(A, b, c);
return (s >= ss); //两面积相等
}
void solve(Node node[], bool flag[]) { //判断一个三角形的三个点是否在三角形内
for (int i = 3; i < 6; ++i) {
flag[i - 3] = isInner(node[i], node[0], node[1], node[2]);
}
}
int main()
{
ios::sync_with_stdio(false);
int T;
cin >> T;
while (T--) {
for (int i = 0; i < 6; ++i)
cin >> node[i].x >> node[i].y;
bool flag[3]; //0外,1内
solve(node, flag);
if (flag[0] && flag[1] && flag[2])puts("contain");
else {
if (flag[0] || flag[1] || flag[2]) puts("intersect");
else {
for (int i = 0; i < 3; ++i)
swap(node[i], node[i + 3]); //换位思考
solve(node, flag);
if (flag[0] && flag[1] && flag[2])puts("contain");
else if (flag[0] || flag[1] || flag[2]) puts("intersect");
else puts("disjoint"); //不相交
}
}
}
return 0;
}
\