博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P1337 [JSOI2004]平衡点 / 吊打XXX
阅读量:6091 次
发布时间:2019-06-20

本文共 2348 字,大约阅读时间需要 7 分钟。

第一道正式的模拟退火。真香!

师兄说我又疯了

这道题要在二维平面上找一个点使这个系统稳定。

化学老师说:能量越低越稳定。这句话在物理也适用。

所以我们要做的就是使这些物品的重力势能尽可能低

但是又不知道绳子长度啊!

傻瓜,只需要在桌子部分的绳子尽量长就可以了啊!

所以我们说到底要求的就是在二维平面上的一个点,满足\(\sum_{m_ig \times dist_i}\)最小。

遇到这种题:模拟退火!!!

我们SA主体的伪代码十分清晰:

设置初始温度T设置当前变量为x和y(这道题中)while T大于一个既定的温度值{    在原x基础上随机向左或向右移动,得到一个新解newx    同理也得到一个newy    // 注意:这里移动的幅度与当前温度T呈正相关,所以乘上去        计算出新解和原解的优值之差DE// 优值就是答案更优更大的意思    if DE > 0    {        当前变量和全局最优的变量都赋为这个新解        当前最优值赋为新解的优值    }    else if(exp(-DE / T) * RAND_MAX > RAND_MAX)// 意思是exp(-DE / T) 大于 1    {        更新当前变量为这个新解,其他的不修改    }    以一个delta来降温}

已经很清晰了,就不再解释了。

最后的一部分就是玄学调参。srand的数很重要。这关系到你是否能满分。。。

不过骗分的话就已经很赚了。

代码:

#include
#include
#include
const int maxn = 1005;const double delta = 0.99;int n;struct Nodes{ int x, y, m;} s[maxn];int sumx, sumy;double ansx, ansy, ans;int read(){ int ans = 0, s = 1; char ch = getchar(); while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar(); return s * ans;}double dist(double x, double y, double xx, double yy){ return sqrt((x - xx) * (x - xx) + (y - yy) * (y - yy));}double cal(double x, double y){ double ret = 0; for(int i = 1; i <= n; i++) ret += s[i].m * dist(s[i].x, s[i].y, x, y); return ret;}void init_SA(){ ansx = (double)(sumx) / (double)(n); ansy = (double)(sumy) / (double)(n); ans = cal(ansx, ansy);}void SA(){ double x = ansx, y = ansy; double T = 2018; while(T > 1e-14)// 3965 { double newx = x + ((rand() << 1) - RAND_MAX) * T; double newy = y + ((rand() << 1) - RAND_MAX) * T; double newans = cal(newx, newy); double DE = ans - newans; if(DE > 0) { x = ansx = newx; y = ansy = newy; ans = newans; } else if(exp(-DE / T) * RAND_MAX > RAND_MAX) { ansx = newx; ansy = newy; } T = T * delta; }}int main(){ srand(19260817); srand(rand()); n = read(); for(int i = 1; i <= n; i++) { s[i].x = read(), s[i].y = read(), s[i].m = read(); sumx += s[i].x; sumy += s[i].y; } init_SA(); for(int i = 1; i <= 10; i++) SA(); printf("%.3lf %.3lf\n", ansx, ansy); return 0;}

转载于:https://www.cnblogs.com/Garen-Wang/p/9737443.html

你可能感兴趣的文章
java:泛型|RandomList
查看>>
iptables 开放所有端口, 对特殊端口只开放给指定IP
查看>>
Xtradb+Haproxy高可用数据库集群(三)sysbench性能测试篇
查看>>
彻底理解Cisco NAT内部的一些事
查看>>
Android官方开发文档Training系列课程中文版:管理Activity的生命周期之Activity的重建...
查看>>
DNS子域授权,acl以及日志系统
查看>>
Linux之bash脚本编程---用户交互
查看>>
揭秘CISCO SDM(安全设备管理工具)
查看>>
<Power Shell>16 禁用用户帐户和Excel查看HTML
查看>>
自动化运维工具Ansible之roles
查看>>
MongoDB分片搭建
查看>>
5、Jenkins Email Extension Plugin插件使用说明
查看>>
Flex(mx:DataGrid)实现数据过滤显示
查看>>
中国ERP三大流程 国外ERP黯然失色
查看>>
js 的 slice方法
查看>>
Java网络编程(一)流
查看>>
Unix整理笔记——安全性——里程碑M13
查看>>
【斗医】【1】Web应用开发20天
查看>>
Zabbix 添加监控主机(linux)及汉化
查看>>
2个月的996模式工作结束了,该继续我的博客了
查看>>