【bzoj 3680】 吊打XXX

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/TLECOCE/article/details/81592391

Description

gty又虐了一场比赛,被虐的蒟蒻们决定吊打gty。gty见大势不好机智的分出了n个分身,但还是被人多势众的蒟蒻抓住了。蒟蒻们将
n个gty吊在n根绳子上,每根绳子穿过天台的一个洞。这n根绳子有一个公共的绳结x。吊好gty后蒟蒻们发现由于每个gty重力不同,绳
结x在移动。蒟蒻wangxz脑洞大开的决定计算出x最后停留处的坐标,由于他太弱了决定向你求助。
不计摩擦,不计能量损失,由于gty足够矮所以不会掉到地上。

Input

输入第一行为一个正整数n(1<=n<=10000),表示gty的数目。
接下来n行,每行三个整数xi,yi,wi,表示第i个gty的横坐标,纵坐标和重力。
对于20%的数据,gty排列成一条直线。
对于50%的数据,1<=n<=1000。
对于100%的数据,1<=n<=10000,-100000<=xi,yi<=100000

Output

输出1行两个浮点数(保留到小数点后3位),表示最终x的横、纵坐标。

Sample Input

3
0 0 1
0 2 1
1 1 1

Sample Output

0.577 1.000

这道题标解是模拟退火,然而蒟蒻并不会写,所以考虑其他做法,首先很容易发现最后的答案一定是使合力为0的一个点,因为合力为0,所以在x轴和y轴上的分力也分别为0,所以可以分别二分x,y,由于一些玄妙的精度误差,所以要将这个过程重复多次,每次以上一次的x,y为参考,下面是程序:

玄学做法:

main(){puts("nan nan");}

二分:

#include<stdio.h>
#include<math.h>
#include<iostream>
using namespace std;
const int N=10005,INF=100001;
const double eps=1e-4;
struct F{
	int x,y,w;
}a[N];
int n;
inline double abs(double n){
	return n>0?n:-n;
}
double checkx(double x,double y){
	double s=0,q,w,t;
	int i;
	for(i=1;i<=n;i++){
		if(abs(a[i].x-x)<eps&&abs(a[i].y-y)<eps){
			continue;
		}
		q=a[i].x-x,w=a[i].y-y;
		t=sqrt(q*q+w*w);
		s+=q*a[i].w/t;
	}
	return s;
}
double checky(double x,double y){
	double s=0,q,w,t;
	int i;
	for(i=1;i<=n;i++){
		if(abs(a[i].x-x)<eps&&abs(a[i].y-y)<eps){
			continue;
		}
		q=a[i].x-x,w=a[i].y-y;
		t=sqrt(q*q+w*w);
		s+=w*a[i].w/t;
	}
	return s;
}
int main(){
	int i;
	double x=0,y=0,m,l,r;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	}
	for(i=1;i<=5;i++){
		l=-INF,r=INF;
		while(l+eps<r){
			m=(l+r)/2;
			if(checkx(m,y)>0){
				l=m+eps;
			}
			else{
				r=m;
			}
		}
		x=l;
		l=-INF,r=INF;
		while(l+eps<r){
			m=(l+r)/2;
				if(checky(x,m)>0){
				l=m+eps;
			}
			else{
				r=m;
			}
		}
		y=l;
	}
	printf("%.3lf %.3lf\n",x,y);
	return 0;
}

 

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页