• [HAOI2006]均分数据


    题解

    今天下午刚学了模拟退火

    借这个题来总结下模拟退火的要注意的问题吧

    1 : (eps)不要设的太大

    2 : 初温(T)在2000左右就差不多可以了

    3 : 注意题目要求是要求最大值还是最小值,当x<0时(exp(x))的取值范围才是(0~1)

    4 : 可以在退完火以后再单独从当前最优答案下进行微调

    5 : 可以进行多次退火

    然后这题就是每次退火就是随机交换序列中的两个数,对序列DP一下就好了

    题解

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    const int M = 25 ;
    const int N = 8 ;
    const double INF = 1e50 ;
    const double EPS = 1e-3 ;
    using namespace std ;
    
    int n , m ;
    int val[M] , e[M] ;
    double f[N][M] , p[M] , Sum[M] ;
    double bax , Ans = INF ;
    inline double Rand() {
    	return (double)((rand() % 101) / 100.0) ;
    }
    inline double F() {
    	for(int i = 0 ; i <= m ; i ++)
    	    for(int j = 0 ; j <= n ; j ++) f[i][j] = INF ;
    	f[0][0] = 0 ;
    	for(int i = 1 ; i <= n ; i ++) Sum[i] = Sum[i - 1] + p[i] ;
    	for(int i = 1 ; i <= m ; i ++)
    	    for(int j = i ; j <= n ; j ++)
    	        for(int k = i - 1 ; k < j ; k ++)
    	            f[i][j] = min(f[i][j] , f[i - 1][k] + (Sum[j] - Sum[k] - bax) * (Sum[j] - Sum[k] - bax)) ;
    	if(f[m][n] < Ans) {
    		Ans = f[m][n] ;
    		for(int i = 1 ; i <= n ; i ++) e[i] = p[i] ;
    	}
    	return f[m][n] ;
    }
    
    inline void Solve() {
    	for(int i = 1 ; i <= n ; i ++) p[i] = e[i] ;
    	double T = 2000 , W = 0.98 ;
    	double NowAns , PreAns , dlt ;
    	while(T > EPS) {
    		PreAns = F() ;
    		int a = rand() % n + 1 , b = rand() % n + 1 ;
    		while(a == b) b = rand() % n + 1 ;
    		swap(p[a],  p[b]) ;
    		NowAns = F() ; dlt = NowAns - PreAns ;
    		if(exp(-dlt / T) > Rand()) ;
    		else  swap(p[a] , p[b]) ;
    	    T *= W ;
    	}
    	for(int i = 1 ; i <= 10000 ; i ++) {
    		int a = rand() % n + 1 , b = rand() % n + 1 ;
    		while(a == b) b = rand() % n + 1 ;
    		swap(p[a] , p[b]) ;
    		F() ;
    		swap(p[a] , p[b]) ;
    	}
    }
    int main() {
    	srand(time(0)) ;
    	cin >> n >> m ;
    	for(int i = 1 ; i <= n ; i ++) {
    		cin >> val[i] ;
    		bax += val[i] ;
    		p[i] = val[i] ;
    	}
    	bax /= m ; F() ;
    	int Times = 20 ; while(Times--) Solve() ;
    	printf("%.2lf
    ",sqrt(Ans / m)) ;
    	return 0 ;
    }
    
  • 相关阅读:
    获取网络时间,减轻自己服务器的请求压力
    mysql学习记录(windows)
    Docker 部署本地pip源
    npm : 无法加载文件 D:vueProject odejs ode_global pm.ps1
    微信小程序没有找到可构建的npm包
    vue 记录 mode:history 模式 踩过的坑
    Linux学习笔记
    kafka监控 Kafka-eagle-web
    vi 分屏 --(visual 可视模式)
    [安卓网络入门] 获取天气
  • 原文地址:https://www.cnblogs.com/beretty/p/10071905.html
Copyright © 2020-2023  润新知