P1337 [JSOI2004]平衡点 / 吊打XXX
题意
有 个重物,重量分别为 ,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞(坐标分别为 ),然后系在一起,形成公共的绳结。
假设绳子不会造成能量损失,桌子足够高而重物不会垂到地上,绳结不会穿过洞或被卡在洞中,且忽略所有的摩擦。问绳结最终平衡于何处。
,。
点击查看题解
题解
假设绳结的位置,对每个对绳结施加的力进行正交分解,利用 方向和 方向上的合力尝试移动绳结(真正的平衡点一定在合力所指向的方向上)。不断缩小移动的距离(绳结不断移动的过程中,系统是不断趋向平衡的,因此每次移动的长度会不断缩小),小于误差值后即可结束程序。
代码
#include<bits/stdc++.h>
using namespace std;
namespace _yz
{
#define E(x) ((x)*(x))
const int N=1000+10;
const double eps=1e-5;
int sx[N],sy[N],sw[N],n;
double x=5000,y=5000;
void check(double move)
{
double tx=0,ty=0,mod;
for(int i=1;i<=n;i++)
{
mod=sqrt(E(sx[i]-x)+E(sy[i]-y));
if(fabs(mod)<eps) continue;
tx+=(sx[i]-x)/mod*sw[i];
ty+=(sy[i]-y)/mod*sw[i];
}
if(fabs(tx)<eps&&fabs(ty)<eps)
{printf("%.3f %.3f\n",x,y); exit(0);}
mod=sqrt(E(tx)+E(ty));
x+=tx/mod*move;y+=ty/mod*move;
}
void yzmain()
{
double T=10000;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",sx+i,sy+i,sw+i);
while(T>eps)
check(T),T*=0.7;
printf("%.3f %.3f\n",x,y);
return;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
_yz::yzmain();
return 0;
}
本文作者:Yurchiu
本文链接:https://yz-hs.github.io/99eea553e2b3/
版权声明:本博客中所有原创文章除特别声明外,均允许规范转载,转载请注明出处。所有非原创文章,按照原作者要求转载。