2019年1月25日训练日记

本来这两天打算补题,后来发现自己做不出来的根本原因还是相关知识点根本就不会。只是浅显的知道这个知识而没有去系统的练习,显然是不可能做出题来的。

相关题目: POJ 1182 食物链(并查集:路径压缩)  这种类型的题目做的还是太少。

补了一道计算几何:不规范相交。并不是严格的不规范相交,而是:

题目:

有一个n个点m条边的图画在了平面上,你想知道有多少对边之间对应的线段相交。

特别地,对于图中的一对边,如果有公共点且只在对应的端点相交,那么我们不认为这对边相交。

思路:

对于没有公共点的两条线段直接上板子就可以了,但是有公共点的需要特判一下共线时候的合法情况。比赛的时候WA了30多发,WA到自闭

代码(来自某位区域赛银牌大佬):

#include<bits/stdc++.h>
using namespace std;

const double eps = 1e-6;

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;
    }
    bool operator == (Point b) const{
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    Point operator - (const Point &b) const{
        return Point(x - b.x, y - b.y);
    }
    double operator ^ (const Point &b) const{
        return x*b.y - y*b.x;
    }
    double operator * (const Point &b) const{
        return x*b.x + y*b.y;
    }
    double distance(Point p){
        return hypot(x - p.x, y - p.y);
    }
}P[1005];

struct Line{
    Point s, e;
    Line(){}
    Line(Point _s, Point _e){
        s = _s; e = _e;
    }
    int segcrossseg(Line v){
        int d1 = sgn((e - s)^(v.s - s));
        int d2 = sgn((e - s)^(v.e - s));
        int d3 = sgn((v.e - v.s)^(s - v.s));
        int 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) ;
    }
    bool check(Line v){
        if(s == v.s){
            Point ss = s;
            double a = ss.distance(e);
            double b = ss.distance(v.e);
            double c = e.distance(v.e);
            if(sgn(b + c - a) == 0 || sgn(a + c - b) == 0)
                return true;
            return false;
        }
        else if(s == v.e){
            Point ss = s;
            double a = ss.distance(e);
            double b = ss.distance(v.s);
            double c = e.distance(v.s);
            if(sgn(b + c - a) == 0 || sgn(a + c - b) == 0)
                return true;
            return false;
        }
        else if(e == v.s){
            Point ss = e;
            double a = ss.distance(s);
            double b = ss.distance(v.e);
            double c = s.distance(v.e);
            if(sgn(b + c - a) == 0 || sgn(a + c - b) == 0)
                return true;
            return false;
        }
        else if(e == v.e){
            Point ss = e;
            double a = ss.distance(s);
            double b = ss.distance(v.s);
            double c = s.distance(v.s);
            if(sgn(b + c - a) == 0 || sgn(a + c - b) == 0)
                return true;
            return false;
        }
        else{
            if(segcrossseg(v) > 0) return true;
            return false;
        }
    }
}L[2005];

int n, m, ans;
pair<int, int> e[2005];

int main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i ++)
        scanf("%d%d", &e[i].first, &e[i].second);
    for(int i = 1; i <= n; i ++)
        scanf("%lf%lf", &P[i].x, &P[i].y);
    for(int i = 1; i <= m; i ++)
        L[i] = Line(P[e[i].first], P[e[i].second]);
    for(int i = 1; i <= m; i ++) for(int j = 1; j < i; j ++)
        if(L[i].check(L[j])) ans ++;
    cout << ans;
    return 0;
}
/*
4 2
1 2
3 4
0 0
2 2
1 1
1 0

3 2
1 2
2 3
0 0
1 1
2 2

4 2
1 2
3 4
0 0
2 2
1 1
3 3

3 2
1 2
2 3
0 0
2 2
1 1
*/

通过这几天各位大佬的讲课,深刻的意识到自己的视野过于狭窄。即使是最基础的知识点,很多简单的推广也是几乎没有见过。

虽然学到一个知识点的时候也试着去拓展,但是还是差远了。对于大佬们的课件,根据我自身的能力,可能要花很长的时间去思考和参悟了。对于一些生疏的知识点,还是要早日理解掌握。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值