模拟退火算法c++

转载. 为方便理解, 在原博客的基础上加部分注释, 原博客地址:http://www.cnblogs.com/CsOH/p/6049117.html 今天终于用模拟退火过了一道题:CodeVS: P1344。有 N ( P2 -> P3 -> ... -> PN 找出 |P1P2|+|P2P3|+...+|PN-1PN| 长度的最小值)  这种问题被称为最优组合问题。传统的动态规划算
摘要由CSDN通过智能技术生成

转载. 为方便理解, 在原博客的基础上加部分注释, 原博客地址:http://www.cnblogs.com/CsOH/p/6049117.html

 

今天终于用模拟退火过了一道题:CodeVS: P1344。

有 N ( <=20 ) 台 PC 放在机房内,现在要求由你选定一台 PC,用共 N-1 条网线从这台机器开始一台接一台地依次连接他们,最后接到哪个以及连接的顺序也是由你选定的,为了节省材料,网线都拉直。求最少需要一次性购买多长的网线。(说白了,就是找出 N 的一个排列 P1 P2 P3 ..PN 然后 P1 -> P2 -> P3 -> ... -> PN 找出 |P1P2|+|P2P3|+...+|PN-1PN| 长度的最小值)

  这种问题被称为最优组合问题。传统的动态规划算法O(n22n)在n = 20的情况下空间、时间、精度都不能满足了。这时应该使用比较另类的算法。随机化算法在n比较小的最优化问题表现较好,我们尝试使用随机化算法。

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>

const int maxn = 21;
double x[maxn], y[maxn];
double dist[maxn][maxn];
int path[maxn];
int n;
double path_dist(){
    double ans = 0;
    for(int i = 1; i < n; i++) {
        ans += dist[path[i - 1]][path[i]];
    }
    return ans;
}
int main(){
    srand(19260817U);                            // 使用确定的种子初始化随机函数是不错的选择 
    scanf("%d", &n);
    for(int i = 0; i < n; i++) scanf("%lf%lf", x + i, y + i);
    for(int i = 0; i < n; i++) for(int j = i + 1; j < n; j++) dist[i][j] = dist[j][i] = hypot(x[i] - x[j], y[i] - y[j]);
    
    for(int i = 0; i < n; i++) path[i] = i;        // 获取初始排列 
    double ans = path_dist();                    // 初始答案 
    int T = 30000000 / n;                         // 单次计算的复杂度是O(n),这里的30000000是试出来的 
    while(T--){
        std::random_shuffle(path, path + n);    // 随机打乱排列 
        ans = std::min(ans, path_dist());        // 更新最小值 
    }
    printf("%.2lf", ans);
}
V
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值