sgu192:RGB(计算几何)

#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int MAXN = 309;
const double eps = 1e-10, INF = 1e9;
int n, tot;
double R, G, B;
double node[MAXN*MAXN];
struct point
{
	double x, y;
	point(double x = 0, double y = 0):x(x),y(y) {};
	void read(){cin >> x >> y;}
};
struct line{point a, b;char c;}seg[MAXN];
typedef point vector;

vector operator * (const double k, const vector u) {return vector(u.x*k, u.y*k);}
vector operator - (const vector a, const vector b) {return vector(a.x-b.x, a.y-b.y);}
vector operator + (const vector a, const vector b) {return vector(a.x+b.x, a.y+b.y);}
vector operator / (const vector a, const double k) {return vector(a.x/k, a.y/k);}

int dcmp(double c) 
{
	if(fabs(c) <= eps) return 0;
	else return c>0?1:-1;	
}

double cross(const vector a, const vector b) {return a.x*b.y-a.y*b.x;} 

bool intersect(const line a, const line b)
{
	point x1 = a.a, y1 = a.b, x2 = b.a, y2 = b.b;
	double c1 = cross(x2-x1, y2-x2), c2 = cross(x1-x2, y1-x1);
	double c3 = cross(x2-y1, y2-x2), c4 = cross(x1-y2, y1-x1);
	if(dcmp(c1*c3) < 0 && dcmp(c2*c4) < 0) return true;
	else return false; 
}

point get(line a, line b)
{
	point p = a.a, q = b.a;
	vector v = a.b-a.a, w = b.b-b.a, u = p-q;
	double t = cross(w, u)/cross(v, w);
	return p+t*v;
}

double get_f(line a, double x)
{
	vector p = a.a, v = (a.b-a.a)/fabs(a.b.x-a.a.x);
	return p.y+(x-p.x)*v.y;	
}

bool cmp(const point a, const point b) 
{
	if(dcmp(a.x-b.x) == 0) return dcmp(a.y-b.y) < 0;
	else return dcmp(a.x-b.x) < 0;	
}

bool inside(line a, double l, double r)
{
	if(dcmp(a.a.x-r) >= 0 || dcmp(l-a.b.x) >= 0) return false;	
	else return true; 	
}

int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)	
	{
		seg[i].a.read();seg[i].b.read();
		if(seg[i].a.x > seg[i].b.x) swap(seg[i].a, seg[i].b);
		node[++tot] = seg[i].a.x, node[++tot] = seg[i].b.x;
		cin >> seg[i].c;	
	}
	for(int i = 1; i <= n; ++i)
		for(int j = i+1; j <= n; ++j)
			if(intersect(seg[i], seg[j]))
				node[++tot] = get(seg[i], seg[j]).x;
	sort(node+1, node+tot+1);
	tot = unique(node+1, node+tot+1)-(node+1); 
	for(int i = 1; i < tot; ++i)
	{
		double mid = (node[i]+node[i+1])/2;
		double min = INF, d = node[i+1]-node[i];
		if(dcmp(d) == 0) continue;
		char c;
		for(int j = 1; j <= n; ++j)
		{
			if(!inside(seg[j], node[i], node[i+1])) continue;
			double high = get_f(seg[j], mid);
			if(high < min)
			{
				min = high;
				c = seg[j].c;	
			}
		}
		if(min < INF)
		{
			switch(c)
			{
				case 'R':R += d;break;
				case 'G':G += d;break;	
				case 'B':B += d;break;
			}
		}
	}
	printf("R %.2lf\n", R);
	printf("G %.2lf\n", G);
	printf("B %.2lf\n", B);
	return 0;	
}

题意:
将每条线段投影到x轴上,每条线段有一个颜色("R"or"G"or"B"),x轴上每一段的颜色取决于最近的线段的颜色。求每一个颜色的长度。
分析:
暴力求出交点后,排序,由于每两个端点之间至多有一种颜色,直接枚举线段即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值