中文题面友链 传送门

Haywire

题目描述
Farmer John’s N cows (4 <= N <= 12, N even) have built a primitive system for communicating between pairs of friendly cows by building wires protected by wrappings made of hay.

Each cow has exactly 3 other friends in the barn, and the cows must arrange themselves to occupy N stalls lined up in a row. A wire of length L requires exactly L units of hay to build, so for example if the cows in stalls 4 and 7 are friends, it would take 3 units of hay to construct a wire to connect them.

Assuming every pair of friends must be connected by a separate wire, please determine the minimum possible amount of hay required to build these wires if the cows order themselves in the best possible way.
输入

  • Line 1: The integer N. FJ’s cows are conveniently numbered 1…N.
  • Lines 2…1+N: Each line contains three space-separated integers in the range 1…N. Line i+1 contains the numeric identifiers of the three friends of cow i. If cow i is a friend of cow j, then j will also be a friend of i.
    输出
  • Line 1: The minimum total amount of hay required to connect all pairs of friendly cows.
    样例输入 Copy
    6
    6 2 5
    1 3 4
    4 2 6
    5 3 2
    4 6 1
    1 5 3
    样例输出 Copy
    17
    提示
    There are 6 cows. Cow 1 is friends with cows 6, 2, and 5, etc.A best ordering of the cows is 6, 5, 1, 4, 2, 3, which requires only 17 units of hay.

朴素随机数法

数据很小,利用随机数计算每次交换的牛的位置,计算出花费,跑1e6次就可以了。(真玄学) 好像只能是1e6,反正1e5是82,5e5是92,越来越接近正解了
注意计算花费时每两头牛都算了两遍,所以结果需要/2.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define I_int ll
inline ll read()
{ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
char F[200];
inline void out(I_int x) {if (x == 0) return (void) (putchar('0'));I_int tmp = x > 0 ? x : -x;if (x < 0) putchar('-');int cnt = 0;while (tmp > 0) {F[cnt++] = tmp % 10 + '0';tmp /= 10;}while (cnt > 0) putchar(F[--cnt]);//cout<<" ";
}
const int maxn=20,mod=1e9+7,tot=1e6;
int pos[maxn][maxn],n,a[maxn],tmp[maxn];
void init(){for(int i=1;i<=n;i++) a[i]=i;
}
int cul(){int sum=0;for(int i=1;i<=n;i++) tmp[a[i]]=i;for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)sum+=abs(tmp[pos[a[i]][j]]-i);return sum/2;//计算时每两个牛的距离都算了都两遍
}
void AC(){n=read();for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)pos[i][j]=read();init();int cnt=1;int minn=2e9;while(cnt<=tot){int l=(rand())%n+1;int r=(rand())%n+1;int t=a[l];a[l]=a[r];a[r]=t;minn=min(minn,cul());cnt++;}out(minn);
}
int main(){AC();return 0;
}

稍加优化的模拟退火

其实本质也是随机数,只是多了一个判断,如果当前解很差的话,就再交换回去。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define I_int ll
inline ll read()
{ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
char F[200];
inline void out(I_int x) {if (x == 0) return (void) (putchar('0'));I_int tmp = x > 0 ? x : -x;if (x < 0) putchar('-');int cnt = 0;while (tmp > 0) {F[cnt++] = tmp % 10 + '0';tmp /= 10;}while (cnt > 0) putchar(F[--cnt]);//cout<<" ";
}
const int maxn=20,mod=1e9+7,tot=5e5;
int pos[maxn][maxn],n,a[maxn],tmp[maxn];
int minn=1e8;
const double s=10000,e=1e-12,c=0.99;
//起始温度 终止温度 温度改变速度
void init(){for(int i=1;i<=n;i++) a[i]=i;
}
int cul(){int sum=0;for(int i=1;i<=n;i++) tmp[a[i]]=i;for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)sum+=abs(tmp[pos[a[i]][j]]-i);return sum/2;//计算时每两个牛的距离都算了都两遍
}
void SA(int times){int x,y,t;while(times--){for(double i=s;i>e;i*=c){do{x=rand()%n+1;y=rand()%n+1;}while(x==y);swap(a[x],a[y]);t=cul();if(minn>=t) minn=t;else if(exp((minn-t)/i)>(double)rand()/RAND_MAX)swap(a[x],a[y]);//当前解很差 恢复此次交换}}return ;
}
void AC(){n=read();for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)pos[i][j]=read();init();SA(160);out(minn);
}
int main(){AC();return 0;
}

几率接受的几率是个很玄学的问题,通常情况,设当前温度为 T T ,当前解为 k k ,最优解为 K_{max} K
max
​ ,我们通常用这样一个玄学公式…
exp((k-kmax)/T)<(double)rand()/RAND_MAX
我当初也不知道exp的意义何在,后来发现太妙了!如果不知道exp是啥,可以自己看一下百科,我稍作解释: exp函数在X < 0时, Y 一定为 0 - 1 之间的小数且单调递增,(double)rand()/RAND_MAX也是一个 0 - 1 之间的小数.这样温度越小,接受当前较差解的几率越低.

最后对比一下两种方法的运行结果吧,其实差不了很多~
朴素版本的随机数

稍加优化的模拟退火
还有个正解是状压dp 想想数据这么小确实可以状压做 未完待续

参考资料:
关于模拟退火的学习笔记 - 李有才99NL的博客 - 洛谷博客
题解 P2210 【Haywire】 - Ciyang 的博客 - 洛谷博客
Haywire (随机数大法好)_weixin_43916298的博客-CSDN博客

UPC Haywire(模拟退火 || 随机数法)相关推荐

  1. 数据结构—— 构造散列函数的六种方法【直接定址法-数字分析法-平方取中法-折叠法-除留余数法-随机数法】

    目录: 一:直接定址法 二:数字分析法 三:平方取中法 四:折叠法 五:除留余数法 六:随机数法 这些方法原理都是将原来数字按某种规律变成另一个数字 一:直接定址法 取关键字的某个线性函数值作为散列地 ...

  2. python生成100个随机数_Python_0——100闭区间产生3个随机数,两种方法排序

    ''' 题目:0--100闭区间产生3个随机数,两种方法排序 法1:暴力遍历 法2:max(a,b,c)min(a,b,c) 注意:random,radint(0--100)产生随机数 '''impo ...

  3. c语言产生随机数_C语言 求的近似值

    点击上方"蓝字"关注我们 愉快的一天,不得不做的三件事: 种田,锄地,整代码!!! [题目] 用循环方法实现. (1)请利用"正多边形逼近"的方法求出π的近似值 ...

  4. 哈希表(闭散列、拉链法--哈希桶)

    哈希表,也称散列表,是一种通过key值来直接访问在内存中的存储的数据结构.它通过一个关键值的函数(被称为散列函数)将所需的数据映射到表中的位置来访问数据. 关于哈希表,主要为以下几个方面: 一.哈希表 ...

  5. 利用开放定址法实现散列表的创建、插入、删除、查找操作_散列表和IO

    散列表(也叫哈希表) 直接寻址法 取关键字或关键字的某个线性函数值为散列地址.即H(key)=key或H(key) = a·key + b,其中a和b为常数(这种散列函数叫做自身函数).若其中H(ke ...

  6. c语言学习进阶-C语言程序产生正态分布随机数

    C语言程序产生正态分布随机数 目录 C语言程序产生正态分布随机数 **中心极限定理(大数定理)** **Hasiting有理逼近法:** **反函数产生给定分布的随机数法:** **Box-Mulle ...

  7. 【数据结构】哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

    一.哈希表 1.概念 哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度.这个 ...

  8. 哈希(散列):(四)C语言实现 哈希 开散列法

    哈希(散列)的概念: https://blog.csdn.net/mowen_mowen/article/details/82943192 C语言实现:静态哈希表: https://blog.csdn ...

  9. html语言随机数,产生随机数的常用方法

    简单随机抽样是一种最简单.最基本的抽样方法,简单随机抽样有两种选取个体的方法:放回和不放回,我们在抽样调查中用的是不放回抽样,常用的简单随机抽样方法有抽签法和随机数法.例:人们打桥牌时,将洗好的扑克牌 ...

最新文章

  1. BZOJ1922: [Sdoi2010]大陆争霸
  2. 《分布式操作系统》知识点(1~7)一
  3. 产品问答 | 入职一家公司,你的选择依据是什么?
  4. 怎么把python解释器配置在pycharm中_在PyCharm中配置项目(三):配置Python解释器...
  5. HTML5-画布(canvas)效果之-渐变色
  6. python安装lxml,在windows环境下
  7. 理论基础 —— 索引 —— 2-3 树
  8. linux转为root用户_[R] 展示linux文件树 - collapsibleTree
  9. 路径压缩_实战|python GUI压缩小程序
  10. VB.NET连接SQL数据库
  11. webservice框架jersey简单总结
  12. 鹰式价差matlab,鹰式期权:什么叫铁鹰式期权组合,蝶式价差期权?
  13. 计算机方面毕业生怎样写简历
  14. 每天一个设计模式——写在前面
  15. 新高考十二种选科情况下,再选科目的考室安排的探索2.0版
  16. CSMA/CD 简要介绍
  17. 数字时代,商业智能BI的落地意味着什么
  18. 简述与机器学习相关的十大常用Python库,极简化算法编程
  19. 前端请求跨域,原来是谷歌浏览器的限制
  20. 数据库(什么是脏读、不可重复读、幻读)

热门文章

  1. Linux系统学习方法论 1
  2. Mac OS下FileVault encryption 使用原理与简介
  3. 软件测试 | 期末复习——软件测试综述
  4. 中文转拼音 中文转罗马声调
  5. AutoCAD Civil 3D创建点文件描述码(点特征码)集控制展点样式与特性
  6. matlab中minigrid,[转载][转载]matlab画地图的工具:worldmap和m_map
  7. 【C++---16】常指针和常引用
  8. 使用sqlcipher打开加密的sqlite方法
  9. 解决KETTLE9 连接MYSQL 8 Error connecting to database: (using class org.gjt.mm.mysql.Driver)
  10. 手机外接usb摄像头软件下载_手机打碟app下载安装_手机打碟软件最新版免费下载...