分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

[luogu1337][bzoj3680][JSOI2004]平衡点 / 吊打XXX

发布时间:2023-09-06 02:35责任编辑:郭大石关键词:暂无标签

题目描述

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

分析

人生中第一道模拟退火题目,感觉模拟退火这个算法非常的优美又非常的(粗鄙之语)。我看不大懂网上那些乱七八糟的什么物理解释,我认为模拟退火就可以用一句话来概括:随机化乱搞,越搞几率越低。而且模拟退火的代码非常简单,但是最最麻烦的就是调参数。
有空的时候我会把模拟退火的学习笔记补起来。
回到这道题目,我们是要找到一个点,使其的合力为\(0\),那么我们首先假设答案就是我们所有点的中点,也就是所有点坐标的平均数,假设这个是我们的答案。然后我们就需要模拟退火找到比这个更好的答案。
我们可以确定一个原点,将所有的力在这个原点上正交分解,最终我们可以得到所有的力的一个合力,而真正的平衡点一定在合力所指向的方向。
每当分得到一个合力之后,将原点在合力的方向上位移一定的距离。每当原点位移的方向发生了改变的时候,缩小以后操作的位移距离。例如:上次操作是将原点像 x 轴正方向移动,而当前移动是将原点像 x 轴负方向上移动,这说明原点的横坐标一定在这两次假设的原点的横坐标中间,因此我们缩小以后原点移动的距离。

ac代码

#include <bits/stdc++.h>#define db double#define N 1005using namespace std;struct node { ???db x, y, w, tot;}a[N], ans;int n;db sqr(db x) { ???return x * x;}db dist(node a, node b) { ???return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}db calc(node p) { ???db res = 0; ???for (int i = 1; i <= n; i ++) ????????res += a[i].w * dist(p, a[i]); ???return res;}db Rand() { ???return rand() % 10000 / 10000.0;}void SA(db T) { ???node now = ans, nw; ???double delta; ???while (T > 1e-4) { ???????nw.x = now.x + T * (2 * Rand() - 1); ???????nw.y = now.y + T * (2 * Rand() - 1); ???????nw.tot = calc(nw); ???????if (nw.tot < now.tot || exp((now.tot - nw.tot) / T) > Rand()) now = nw; ???????if (nw.tot < ans.tot) ans = nw; ???????T = T * 0.98; ???} ???for (int i = 1; i <= 1500; i ++) { ???????nw.x = ans.x + T * (2 * Rand() - 1); ???????nw.y = ans.y + T * (2 * Rand() - 1); ???????nw.tot = calc(nw); ???????if (nw.tot < ans.tot) ans = nw; ???}}int main() { ???srand(20040127); ???scanf("%d", &n); ???for (int i = 1; i <= n; i ++) { ???????scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].w); ???????ans.x += a[i].x; ???????ans.y += a[i].y; ???} ???ans.x /= n; ???ans.y /= n; ???ans.tot = calc(ans); ???for (int i = 1; i <= 150; i ++) SA(100000); ???printf("%.3lf %.3lf\n", ans.x, ans.y); ???return 0;}

[luogu1337][bzoj3680][JSOI2004]平衡点 / 吊打XXX

原文地址:https://www.cnblogs.com/chhokmah/p/10529557.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved