【几何】[CQOI]RGB
已知平面上的 n 条线段, 第 i 条线段由两个端点 给出。任意两条不同的线段至多只有一个公共点。 每条线段被染为红(R)绿(G)蓝(B)三种颜色之一。 现将所有的线段投影到 X 轴。若有若干条线段上的点P1 P2 P3 …投影到 X 轴上的同一个点 Q,那么 Q 的颜色定义为距离 Q 最近的Pn的颜色。 求 X 轴上三种颜色线段各自的总长度。
【样例输入】
4
1 1 3 2 R
2 1 4 2 G
3 1 5 2 B
2 2 3 5 R
【样例输出】
R 1.00
G 1.00
B 2.00
解题思路,这个就是个裸题,但是因为只有300暴力求出所有的线段的交点(忘了怎么求了, 用的解析式) 然后把交点和线段的端点放到数组里面,然后对每个相邻的点连线取投影的中点暴力枚举每一条线段那一条的交点的abs(y) 最小就行了。
代码如下:
#include <bits/stdc++.h>
using namespace std;
const double INF = 1e10;
const double eps = 1e-4;
struct Point{
double x, y;
Point(){x=y=0.0;}
Point(double _x, double _y):x(_x), y(_y){}
bool operator == (const Point &p) const {
return p.x == x && p.y == y;
}
};
const Point P_INF(-INF, -INF);
struct Line{
int Color;
Point p1, p2;
double k, b;
Line(){k = b = 0; Color = 0; p1 = p2 = P_INF;}
Line(Point _p1, Point _p2){
p1 = _p1;
p2 = _p2;
k = (p1.y - p2.y) / (p1.x - p2.x);
b = p1.y - p1.x * k;
}
Point GetIntersection(Line t){
if(t.k >= k - eps && t.k <= k + eps){
if(t.p1 == p2)
return t.p1;
if(t.p2 == p1)
return t.p2;
return P_INF;
}
Point ans;
ans.x=(t.b-b)/(k-t.k);
ans.y=k*ans.x+b;
double pos = ans.x;
return ((pos - p1.x) * (pos - p2.x) < 0 && (pos - t.p1.x) * (pos - t.p2.x) < 0 )?ans:P_INF;
}
double get_y(double pos){
if((pos - p1.x) * (pos - p2.x) > 0) return INF;
return (pos - p1.x)*(p2.y - p1.y)/(p2.x - p1.x)+p1.y;
}
};
const int MAXN = 400000;
Point pque[MAXN+10];
int pcnt;
double colors[5];
bool cmp(Point a, Point b){
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}
void Init(Line lines[], int n){
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
Point res = lines[i].GetIntersection(lines[j]);
if(res == P_INF) continue;
pque[pcnt++] = res;
}
}
for(int i=0;i<n;i++){
pque[pcnt++] = lines[i].p1;
pque[pcnt++] = lines[i].p2;
}
sort(pque, pque+pcnt, cmp);
for(int i=0;i<pcnt-1;i++){
double Min = INF, mid=(pque[i+1].x+pque[i].x)/2.0;
int Color = 0;
for(int j=0;j<n;j++){
if(lines[j].get_y(mid) < Min){
Min = lines[j].get_y(mid);
Color = lines[j].Color;
}
}
if(Color==0)continue;
colors[Color] += pque[i+1].x-pque[i].x;
}
}
Line nds[310];
int main(){
//Judge(5);
int n;
double t1, t2, t3, t4;
char tmp[4];
scanf("%d", &n);
for(int i=0;i<n;i++){
scanf("%lf %lf %lf %lf", &t1, &t2, &t3, &t4);
scanf("%s", tmp);
if(t1 >= t3-eps && t1 <= t3+eps){i--, n--; continue;}
nds[i] = Line(Point(t1, t2), Point(t3, t4));
if(t1 > t3) swap(nds[i].p1, nds[i].p2);
nds[i].Color = tmp[0] == 'R' ? 1 : (tmp[0] == 'G' ? 2 : 3);
}
Init(nds, n);
printf("R %.2lf\nG %.2lf\nB %.2lf\n", colors[1], colors[2], colors[3]);
return 0;
}