Yurchiu's Blog

一些关于计算几何的题目

Yurchiu 2021-07-09, 11:11:27 488 隐藏左右两栏 展示左右两栏

P1337 [JSOI2004]平衡点 / 吊打XXX

题意

nn 个重物,重量分别为 wiw_i,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞(坐标分别为 (xi,yi)(x_i,y_i)),然后系在一起,形成公共的绳结。

假设绳子不会造成能量损失,桌子足够高而重物不会垂到地上,绳结不会穿过洞或被卡在洞中,且忽略所有的摩擦。问绳结最终平衡于何处。

1n,w10001\le n,w\le100010000x,y10000-10000\le x,y\le10000

点击查看题解

题解

假设绳结的位置,对每个对绳结施加的力进行正交分解,利用 xx 方向和 yy 方向上的合力尝试移动绳结(真正的平衡点一定在合力所指向的方向上)。不断缩小移动的距离(绳结不断移动的过程中,系统是不断趋向平衡的,因此每次移动的长度会不断缩小),小于误差值后即可结束程序。

代码

#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/

版权声明:本博客中所有原创文章除特别声明外,均允许规范转载,转载请注明出处。所有非原创文章,按照原作者要求转载。


By Yurchiu.
其他物件杂物收纳
Hitokoto

Yurchiu 说,除了她以外的人都很强!嘤嘤嘤~~
博客信息
文章数目
158
最近更新
08-21
本站字数
350.6k
文章目录