• BZOJ3680:吊打XXX(模拟退火)


    Description

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

    Input

    输入第一行为一个正整数n(1<=n<=10000),表示gty的数目。
    接下来n行,每行三个整数xi,yi,wi,表示第i个gty的横坐标,纵坐标和重力。
    对于20%的数据,gty排列成一条直线。
    对于50%的数据,1<=n<=1000。
    对于100%的数据,1<=n<=10000,-100000<=xi,yi<=100000

    Output

    输出1行两个浮点数(保留到小数点后3位),表示最终x的横、纵坐标。

    Sample Input

    3
    0 0 1
    0 2 1
    1 1 1

    Sample Output

    0.577 1.000

    Solution

    模拟退火入门题
    将初始最优解设置为x的平均值和y的平均值
    退火的时候记得时刻更新全局最优解
    退火完后再在最优解位置随机方向跳几下来保证能到达最优解
    然后再玄学调参就可以过了

    PS:luogu要过的话下面的代码T要从100改成1000,0.98要改成0.985

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<cmath>
     6 using namespace std;
     7 
     8 int n,x[10010],y[10010],w[10010];
     9 double eps=1e-3,minn=1e15;
    10 
    11 struct Node{double x,y;}ans;
    12 double Rand(){return rand()%100001/100000.0;}
    13 
    14 double f(Node p)
    15 {
    16     double tot=0;
    17     for (int i=1; i<=n; ++i)
    18     {
    19         double delx=p.x-x[i];
    20         double dely=p.y-y[i];
    21         tot+=sqrt(delx*delx+dely*dely)*w[i];
    22     }
    23     if (tot<minn) minn=tot,ans=p;
    24     return tot;
    25 }
    26 
    27 void Simulate_Anneal()
    28 {
    29     double T=100;
    30     Node now=ans;
    31     while (T>eps)
    32     {
    33         Node nxt;
    34         nxt.x=now.x+T*(2*Rand()-1);
    35         nxt.y=now.y+T*(2*Rand()-1);
    36         double delta=f(nxt)-f(now);
    37         if (delta<0 || exp(-delta/T)>Rand())
    38             now=nxt;
    39         T*=0.98;
    40     }
    41     for (int i=1; i<=5000; ++i)
    42     {
    43         now.x=ans.x+T*(2*Rand()-1);
    44         now.y=ans.y+T*(2*Rand()-1);
    45         f(now);
    46     }
    47     printf("%.3lf %.3lf",ans.x,ans.y);
    48 }
    49 
    50 int main()
    51 {
    52     scanf("%d",&n);
    53     for (int i=1; i<=n; ++i)
    54     {
    55         scanf("%d%d%d",&x[i],&y[i],&w[i]);
    56         ans.x+=x[i],ans.y+=y[i];
    57     }
    58     ans.x/=n; ans.y/=n; f(ans);
    59     Simulate_Anneal();
    60 }
  • 相关阅读:
    PTA 5-3 树的同构 ——理解递归
    停车管理系统
    两个有序链表序列的合并 (15分)
    lua 面向对象笔记 继承 和 组合
    二叉树高度计算,判定是否为平衡二叉树
    会用git的重要性,记工作中使用git reset 代码丢失的教训
    #include <bits/stdc++.h> 万能头文件
    C++中类的静态变量成员
    C++创建对象加括号和不加括号的区别
    deepin(深度系统)安装微信 qq
  • 原文地址:https://www.cnblogs.com/refun/p/9282249.html
Copyright © 2020-2023  润新知