【luoguP1337】[JSOI2004]平衡点

题目描述

如图:有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。

问绳结X最终平衡于何处。

注意:桌面上的洞都比绳结X小得多,所以即使某个重物特别重,绳结X也不可能穿过桌面上的洞掉下来,最多是卡在某个洞口处。

输入输出格式

输入格式:

文件的第一行为一个正整数n(1≤n≤1000),表示重物和洞的数目。接下来的n行,每行是3个整数:Xi.Yi.Wi,分别表示第i个洞的坐标以及第 i个重物的重量。(-10000≤x,y≤10000, 0

输出格式:

你的程序必须输出两个浮点数(保留小数点后三位),分别表示处于最终平衡状态时绳结X的横坐标和纵坐标。两个数以一个空格隔开。

输入输出样例

输入样例#1:
3
0 0 1
0 2 1
1 1 1
输出样例#1:
0.577 1.000






说明

[JSOI]


很有意思的题目。。。

用到了一种调整的思想

先设平衡点为x,y,然后对所有的点产生的力正交分解,然后算合力

把平衡点向合力方向调整一个尺度k,k是自定的一个常数,且随着调整次数的增多而不断减小

于是这样就可以求得近似解


PS.好像一些求近似解的题目都可以利用调整或者估算的思想瞎搞一波。。。


代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;
typedef long double DL;

const int d = 1001;
const int maxn = 1010;
const DL eps = 1e-10;

int n;
DL k = 1000000,presumx,presumy;
DL x[maxn],y[maxn],w[maxn];

inline LL getint()
{
	LL ret = 0,f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		ret = ret * 10 + c - '0',c = getchar();
	return ret * f;
}

int main()
{
	n = getint();
	for (int i = 1; i <= n; i++)
	{
		x[i] = getint();
		y[i] = getint();
		w[i] = getint();
	}
	DL ox = 0,oy = 0;
	for (int s = 1; s <= d; s++)
	{
		DL sumx = 0,sumy = 0;
		for (int i = 1; i <= n; i++)
		{
			DL a = x[i] - ox,b = y[i] - oy;
			DL dis = sqrt(a * a + b * b);
			if (abs(dis) > eps) sumx += a / dis * w[i];
			if (abs(dis) > eps) sumy += b / dis * w[i];
		}
		DL c = sqrt(sumx * sumx + sumy * sumy);
		k *= 0.7;
		if (abs(k) <= eps) break;
		if (abs(c) <= eps) break;
		ox += sumx / c * k;
		oy += sumy / c * k;
	}
	printf("%.3Lf %.3Lf",ox,oy);
	return 0;
}


你可能感兴趣的:(模拟,瞎搞)