Problem I
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 56 Accepted Submission(s) : 9
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
在几何的世界里,有一个圆和一个三角形,现在分别告诉他们的位置,请编程判断他们之间的位置关系,是不是很简单呢?祝你好运吧~
Input
多组测试数据,第一行有一个整数t(1<=t<=100)代表case数量,对于每个case,第一行有三个整数x,y,r分别代表圆心的位置和半径,第二行有6个整数分别代表三角形的三个点(对于所有坐标绝对值小于1000,0<r<1000)
Output
每个case形如"Case #K: M",K代表case数,从1开始,M代表它们之间的关系。(如果相离或者相切输出"OO",如果三角形包含圆或者圆包含三角形输出"II",部分相交则输出"XX")
Sample Input
3 0 0 1 -5 -5 0 5 5 0 0 0 1 -2 -1 0 1 2 1 0 0 1 5 5 6 5 6 6
Sample Output
Case #1: II Case #2: XX Case #3: OO
#define DeBUG
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <map>
#include <list>
#include <bitset>
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-9
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 100005
struct Point;
typedef Point Vec;
struct Point
{
double x, y;
Point () {}
Point(double a, double b)
{
x = a;
y = b;
}
Vec operator + (const Vec &b)//点加法
{
return Vec(x + b.x, y + b.y);
}
Vec operator - (const Vec &b)//点减法
{
return Vec(x - b.x, y - b.y);
}
Vec operator * (const double &p)//点与常数相乘
{
return Vec(x * p, y * p);
}
Vec operator / (const double &p)//点除以常数
{
return Vec(x / p, y / p);
}
bool operator < (const Point &b)//平面直角坐标系中左下方的为小
{
return x < b.x || (sgn(x - b.x) == 0 && y < b.y);
}
bool operator == (const Point &b)//点相等判断
{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
};
double dis(Point a, Point b)
{
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
inline double dotDet(Vec a, Vec b)//点乘
{
return a.x * b.x + a.y * b.y;
}
inline double crossDet(Vec a, Vec b)//叉乘
{
return a.x * b.y - a.y * b.x;
}
inline double crossDet(Point o, Point a, Point b)//向量叉乘
{
return crossDet(a - o, b - o);
}
inline double triArea(Point o, Point b, Point c)//三点求三角形面积
{
return fabs(crossDet(b - o, c - o)) / 2;
}
inline bool onSeg(Point x, Point a, Point b)//判断点在线段ab上,加上||x==a||x==b在端点也算
{
return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0 || x == a || x == b;
}
inline double vecLen(Vec a)//求一点到原点距离
{
return sqrt(dotDet(a, a));
}
double pt2Line(Point x, Point a, Point b)//这里已经fabs保证为正,x到直线ab的距离(投影),注意被投影向量为ax,投向ab
{
Vec v1 = b - a, v2 = x - a;
return fabs(crossDet(v1, v2) / vecLen(v1));
}
// Polygon class
struct Poly//平面类
{
vector<Point> pt;//保存平面对应的端点
Poly()
{
pt.clear();
}
~Poly() {}
Poly(vector<Point> pt): pt(pt) {} //使用vector进行初始化
Point operator [](int x) const//重载[]返回对应端点
{
return pt[x];
}
int size()//返回对应平面点数
{
return pt.size();
}
} ;
int ptInPoly(Point p, Poly &poly)//判断点在多边形内,用vector<Point>初始化多边形,-1在边上,0在外面,1在里面
{
int wn = 0, sz = poly.size();
for (int i = 0; i < sz; i++)
{
if (onSeg(p, poly[i], poly[(i + 1) % sz])) return -1;
int k = sgn(crossDet(poly[(i + 1) % sz] - poly[i], p - poly[i]));
int d1 = sgn(poly[i].y - p.y);
int d2 = sgn(poly[(i + 1) % sz].y - p.y);
if (k > 0 && d1 <= 0 && d2 > 0) wn++;
if (k < 0 && d2 <= 0 && d1 > 0) wn--;
}
if (wn != 0) return 1;
return 0;
}
double pt2Seg(Point x, Point a, Point b)//x在线段ab上的投影,这里保证为正
{
if (a == b) return vecLen(x - a);
Vec v1 = b - a, v2 = x - a, v3 = x - b;
if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
return fabs(crossDet(v1, v2)) / vecLen(v1);
}
bool incirle(Point p[], Point o, double r)
{
int flag = 0;
for (int i = 0; i < 3; i++)
{
if (sgn(r - dis(o, p[i])) < 0)
return 0;
}
return 1;
}
int outtri1(Point p[], Point o, double r)
{
for (int i = 0; i < 3; i++)
{
if (sgn(r - pt2Line(o, p[i], p[i + 1])) > 0)
{
return 0;
}
}
return 1;
}
int outtri(Point p[], Point o, double r)
{
for (int i = 0; i < 3; i++)
{
if (sgn(r - dis(o, p[i])) > 0)
return 0;
}
for (int i = 0; i < 3; i++)
{
if (sgn(r - pt2Seg(o, p[i], p[i + 1])) > 0)
{
return 0;
}
}
return 1;
}
int cnt = 1;
int main()
{
#ifdef DeBUGs
freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--)
{
double x, y, r;
scanf("%lf%lf%lf", &x, &y, &r);
std::vector<Point> v;
Point p[5];
for (int i = 0; i < 3; i++)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
v.push_back(p[i]);
}
p[3] = p[0];
Poly tri(v);
Point o(x, y);
printf("Case #%d: ", cnt++);
int flag = 0;
if(incirle(p, o, r))//先判断三角形在圆内
{
printf("II\n");
}
else if (ptInPoly(o, tri) == 1)//如果点在三角形内两种情况
{
if (outtri1(p, o, r))//不相交
{
printf("II\n");
}
else
{
printf("XX\n");
}
}
else
{
if (outtri(p, o, r))//圆心在三角形外且不相交
{
printf("OO\n");
}
else
printf("XX\n");
}
}
return 0;
}