本来这两天打算补题,后来发现自己做不出来的根本原因还是相关知识点根本就不会。只是浅显的知道这个知识而没有去系统的练习,显然是不可能做出题来的。
相关题目: 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
*/
通过这几天各位大佬的讲课,深刻的意识到自己的视野过于狭窄。即使是最基础的知识点,很多简单的推广也是几乎没有见过。
虽然学到一个知识点的时候也试着去拓展,但是还是差远了。对于大佬们的课件,根据我自身的能力,可能要花很长的时间去思考和参悟了。对于一些生疏的知识点,还是要早日理解掌握。