`

hdu3819

阅读更多

/*
这个题需要注意的是整体上不单调的,所以不能一开始就用二分法求解,而是先从下往上一段段的判断,
直到找到某一段不满足条件了就用二分法。  
*/
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 105;
const double eps = 1e-10;
struct point{
	double x, y;
	point(double _x=0, double _y=0) : x(_x), y(_y) {}
	void read(){
		scanf("%lf%lf", &x, &y);
	}
}ps[N*2+10];
int m, n;
point pl[N], pr[N];
int sign(double d){
	return d < -eps ? -1 : (d > eps);
}

//计算多边形的有向面积,点集序列为逆时针时为正,否则为负
double polyArea(point* ps, int n){
	ps[n] = ps[0];
	int i;
	double ans=0;
	for(i = 0; i < n; i++){
		ans += (ps[i].x*ps[i+1].y-ps[i].y*ps[i+1].x);
	}
	return ans/2.0;
}
//求多边形的重心
point polyCentroid(point* ps, int n){
	point ans(0,0);
	double area;
	int i;
	area = polyArea(ps, n);
	//if(sign(area) == 0) return ans;
	if(sign(area) == 0) return ps[0];
	ps[n] = ps[0];
	for(ans.x = ans.y = i = 0; i < n; i++){
		ans.x += (ps[i].x+ps[i+1].x)*(ps[i].x*ps[i+1].y-ps[i].y*ps[i+1].x);
		ans.y += (ps[i].y+ps[i+1].y)*(ps[i].x*ps[i+1].y-ps[i].y*ps[i+1].x);
	}
	ans.x /= (area*6.0);
	ans.y /= (area*6.0);
	return ans;
}
bool input(){
	scanf("%d%d", &m, &n);
	int i;
	for(i = 0; i < m; i++){
		pl[i].read();
	}
	for(i = 0; i < n; i++){
		pr[i].read();
	}
	return true;
}
double getx(point low, point high, double y){
	return low.x - ((y - low.y) * (low.x - high.x) / (high.y - low.y));
}
void getPoly(point* ps, int& cnt, double y){
	int i, j;
	cnt = 0;
	for(i = 0; i < m && pl[i].y <= y; i++) ;
	if(i >= m){
		i = m-1;
	}else{
		ps[cnt].x = getx(pl[i-1], pl[i], y);
		ps[cnt++].y = y;
		i--;
	}
	for(; i >= 0; ps[cnt++] = pl[i--]);
	for(i = 0; i < n && pr[i].y <= y; i++) ;
	for(j = 0; j < i; ps[cnt++] = pr[j++]) ;
	if(i < n){
		ps[cnt].x = getx(pr[i-1], pr[i], y);
		ps[cnt++].y = y;
	}
}
bool check(double y){
	int cnt;
	getPoly(ps, cnt, y);
	point mid = polyCentroid(ps, cnt);
	return sign(mid.x-pl[0].x) >= 0 && sign(mid.x-pr[0].x) <= 0;
}
void solve(){
	int li, ri;
	double ans=0, y, l, r, mid;
	char op;
	li = ri = 0;
	while(true){
		if(li == m || ri == n){
			ans = min(pl[m-1].y, pr[n-1].y);
			break;
		}
		if(pl[li].y < pr[ri].y){
			op = 'l';
			y = pl[li].y;
		}else{
			op = 'r';
			y = pr[ri].y;
		}
		if(!check(y)){
			l = max(pl[li-1].y, pr[ri-1].y);
			r = y;
			while(l <= r){
				mid = (l+r)*0.5;
				if(check(mid)){
					l = mid+eps;
				}else{
					r = mid-eps;
				}
			}
			ans = l-eps;
			break;
		}
		if(op == 'l') li++;
		else ri++;
	}
	printf("%.3lf\n", ans);
}

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		input();
		solve();
	}
	return 0;
}
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics