JSOI平衡点

[JSOI2004]平衡点 / 吊打XXX

被吊打了啊 !

这道题, 看上去真的挺难的 .

简言之, 就是求平衡状态时, 中心点的位置 .

做出受力分析图, 我们可以看得出来, 这个点的位置, 其实与绳子是无关的, 每根绳的拉力, 也一定是等于重物的

所以, 我们可以先随机一个点, 求出这\(n\)根线对着个点的作用力的合力. 因为力的方向不好表示, 所以我们可以正交分解, 将力分解到\(x\)轴和\(y\)轴上去.

这个点必定会沿合力方向移动一定的距离, 直到合力为零.

但是, 我们在不用其他数学工具的情况下, 我们可以随机一个较大步长, 然后不断地缩小这个步长, 就可以越来越接近这个目标点了.

当某一次的移动前后的变化小于精度范围时, 那么我们就找到答案了.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <bits/stdc++.h>

using namespace std;

const int Maxn = 1005;
int N;
double X, Y;
bool Xf(1), Yf(1);
struct Node
{
int X, Y, G;
}Points[Maxn];

inline void Solve(double M)
{
double x(0), y(0), Temp;
for (int i = 1; i <= N; ++i)
{
Temp = sqrt((X - Points[i].X) * (X - Points[i].X) + (Y - Points[i].Y) * (Y - Points[i].Y));
if (!Temp) continue;
x += Points[i].G / Temp * (Points[i].X - X);
y += Points[i].G / Temp * (Points[i].Y - Y);
}
Temp = sqrt(x * x + y * y);
Y += M / Temp * y;
X += M / Temp * x;
}

int main()
{
scanf ("%d", &N);
for (int i = 1; i <= N; ++i)
scanf ("%d %d %d", &Points[i].X, &Points[i].Y, &Points[i].G);

double M = 10000, tx, ty;
while (1)
{
tx = X, ty = Y;
Solve(M);
if (abs(tx - X) < 0.00001 && abs(ty - Y) < 0.00001) break;
M *= 0.9;
}
printf ("%.3lf %.3lf\n", X, Y);
system ("pause");
}