Two Ants(分类讨论)

Two Ants

[Link](Problem - L - Codeforces)

题意

给你两个线段 w 和 b w和b wb,问你站在 b b b上平面上你看不到的区域的面积是多少。

题解

根据两直线的关系,讨论出所有的 0 和 i n f 0和inf 0inf的情况,再对于可以算的情况求解即可。
在这里插入图片描述

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 1e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k,  C = 0;
int a[N];
int sgn(double x) {
    if (fabs(x) < eps) return 0;
    if (x < 0) return -1;
    return 1;
}
struct Point {
double x, y;
Point() {}
Point (double _x, double _y) {
x = _x, y = _y;
}
void input() {
scanf("%lf%lf", &x, &y);
}
void output() {
printf("%.2lf %.2lf", x, y);
}
bool operator ==(Point b) const{
return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
}
bool operator <(Point b) const{
return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
}
Point operator -(const Point &b) const{
return Point(x - b.x, y - b.y);
}
Point operator +(const Point &b) const{
return Point(x + b.x, y + b.y);
}
Point operator *(const double &t) const{
return Point(x * t, y * t);
}
Point operator /(const double &t) const{
return Point(x / t, y / t);
}
//cross
double operator ^(const Point &b) const{
return x * b.y - y * b.x;
}
// dot
double operator *(const Point &b) const{
return x * b.x + y * b.y;
}
double len() {
return hypot(x, y);
}
double len2() {
return x * x + y * y;
}
double distance(Point p) {
return hypot(x - p.x, y - p.y);
}
// pa pa 夹角 
double rad(Point a, Point b) {
Point p = *this;
return fabs(atan2(fabs((a - p) ^ (b - p)), (a - p) * (b - p)));
}
// 转化为长度为r的向量
Point trunc(double r) {
double l = len();
if (!sgn(l)) return *this;
r /= l;
return Point(x * r, y * r);
}
//逆时针旋转90度
Point rotleft() {
return Point(-y, x);
}
//顺时针旋转90度
Point rotright() {
return Point(y, -x);
}
// 绕着p点逆时针旋转 rad度
Point rotate(Point p, double rad) {
Point v = (*this) - p;
double c = cos(rad), s = sin(rad);
return Point(p.x + v.x * c - v.y * s, p.y + v.x * s + v.y * c);
}
};
typedef Point Vector;
struct Line {
   Point s, e;
   Line() {}
   Line(Point _s, Point _e) {
        s = _s, e = _e;
   }
      // 根据一个点和倾斜角 angle 确定直线, 0<=angle< pis
   Line(Point p, double angle) {
      s = p;
     if (sgn(angle - pi / 2) == 0)    e = (s + Point(0, 1));
     else e = (s + Point(1, tan(angle))); // 往上平移
}
//ax + by + c = 0;
Line(double a, double b, double c) {
if (!sgn(a)) {
s = Point(0, -c / b);
e = Point(1, -c / b);
}
else if (!sgn(b)) {
s = Point(-c / a, 0);
e = Point(-c / a, 1);
}
else {
s = Point(0, -c / b);
e = Point(1, (-c - a) / b);
}
}
bool operator ==(Line v) {
return (s == v.s) && (e == v.e);
}
void input() {
s.input(), e.input();
}
void adjust() {
if (e < s) swap(s, e);
}
// 线段长度
double length() {
return s.distance(e);
}
// 直线倾斜角 0<=angle<pi
double angle() {
double k = atan2(e.y - s.y, e.x - s.x);
if (sgn(k) < 0) k += pi;
if (sgn(k - pi) == 0) k -= pi;
return k;
}
// 点和线的关系 1.左边 2.右边 3.线上
int relation(Point p) {
int c = sgn((p - s) ^ (e - s));
if (c < 0) return 1;
else if (c > 0) return 2;
return 3;
}
//点在线段上
bool pointonseg(Point p) {
return sgn((p-s)^(e-s)) == 0 && sgn((s-p)*(e-p)) <= 0;
}
// 两直线平行
bool parallel(Line v) {
return sgn((e - s) ^ (v.e - v.s)) == 0;
}
// 两线段相交判断  2 规范相交 1 不规范相交 0 不相交
int segcrossseg(Line v) {
int d1 = sgn((e-s)^(v.s-s)), d2 = sgn((e-s)^(v.e-s));
int d3 = sgn((v.e-v.s)^(s-v.s)), d4 = sgn((v.e-v.s)^(e-v.s));
if ((d1^d2) == -2 && (d3^d4) == -2) return 2;
return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
 (d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
 (d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
 (d4==0 && sgn((e-v.s)*(e-v.e))<=0);
}
// 直线和线段相交判断 2 规范相交 1 不规范相交 0 不相交 this line v seg
int linecorssseg(Line v) {
int d1 = sgn((e-s)^(v.s-s)), d2 = sgn((e-s)^(v.e-s));
if ((d1^d2) == -2) return 2;
return (!d1 || !d2); 
}
// 两直线关系 0 平行 1 重合 2 相交
int linecrossline(Line v) {
if ((*this).parallel(v)) return v.relation(s) == 3;
return 2; 
}
// 求两直线的交点,保证不平行和重合
Point crossPoint(Line v) {
double a1 = (v.e-v.s)^(s-v.s), a2 = (v.e-v.s)^(e-v.s);
return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
}
double dispointtoline(Point p) {
return fabs((e-s)^(p-s)) / length();
}
double dispointtoseg(Point p) {
if (sgn((e-s)*(p-s)) < 0 || sgn((e-s)*(p-e)) < 0) return min(p.distance(s), p.distance(e));
return dispointtoline(p);
}
// 返回线段和线段的距离,保证不能相交
double dissegtoseg(Line v) {
return min(min(dispointtoseg(v.s), dispointtoseg(v.e)), 
min(v.dispointtoseg(s), v.dispointtoseg(e)));
}
// 返回点p在直线上的投影
Point lineprog(Point p) {
return s + (((e-s)*((e-s)*(p-s))/(e-s).len2()));
}
};
Point w1, w2, b1, b2, p;
void check() {
    cout << "Case "<< ++ C <<": ";
    if (w1 == b1 || w1 == b2 || w2 == b1 || w2 == b2) { 
        if (sgn((w2 - w1) ^ (b2 - b1)) == 0) {
            cout << 0 << endl;
            return ;
        }
        else {
            cout << "inf" << endl;
            return ;
        }
    }
    if (Line(w1, w2).segcrossseg(Line(b1, b2))) { 
        if (Line(w1, w2).pointonseg(b1) || Line(w1, w2).pointonseg(b2)) {
            cout << "inf" << endl;
            return ;
        }
        else if (Line(b1, b2).pointonseg(w1) || Line(b1, b2).pointonseg(w2)) {
            cout << 0 << endl;
            return ;
        }
        else {
            cout << 0 << endl;
            return ;
        }
    }
    if (!sgn((w1 - b1) ^ (w2 - b1)) && !sgn((w1 - b2) ^ (w2 - b2))) { 
        cout << 0 << endl;
        return ;
    }
    if (!Line(w1, w2).parallel(Line(b1, b2))) { 
        p = Line(w1, w2).crossPoint(Line(b1, b2));
        if (Line(w1, w2).pointonseg(p)) {
            cout << "inf" << endl;
            return ;
        }
        else if (Line(b1, b2).pointonseg(p)) {
            cout << 0 << endl;
            return ;
        }
    }
    if (Line(b1, w1).segcrossseg(Line(b2, w2))) swap(w1, w2); 
    if (Line(b1, w1).parallel(Line(b2, w2))) {
        cout << "inf" << endl;
        return ;
    }
    p = Line(b1, w1).crossPoint(Line(b2, w2));
    double s1 = ((w2 - w1) ^ (p - w1)), s2 = ((w2 - w1) ^ (b1 - w1));
    if (sgn(s1) * sgn(s2) > 0) {
        cout << "inf" << endl;
        return ;
    }
    else {
        s1 = fabs(s1) / 2.0;
        cout << setiosflags(ios::fixed)<< setprecision(8) << s1 << endl;
        return ;
    }
}
int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    int T;
    cin >> T;
    while (T -- ) {
        cin >> w1.x >> w1.y >> w2.x >> w2.y;
        cin >> b1.x >> b1.y >> b2.x >> b2.y;
        check();
    }
    return 0;
}
// 相交  
// 端点相交 1.共线 0  2.不共线 inf
// 非端点相交  1. 一个在另一个线上 1.b在w inf   2.w在b 0
// 规范相交   0

//不相交
// 平行共线 0 
// 不平行 某一个线段的延长线交到另一个线段上 b交w inf w交b 0
//根据交线求面积 
// 保证b1w1 b2w2不相交
// b1w1 b2w2 平行 inf
// 求面积如果 如果w在中间返回面积, 否则 inf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值