退火求助
查看原帖
退火求助
366937
too_simple楼主2022/10/1 18:28
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <ctime>

using namespace std;

const double down = 0.99, endt = 1e-15;

int n, m;
int p[21], pp[21];
double aver, a[21], ans;

int Rand(int a, int b) {
    return (rand() + b) % b + a;
}

double sum() {
    double ans1 = 0;
    for(int i = 0; i <= m - 1; ++ i) {
        double sum1 = 0;
        for(int j = 1; j <= (n / m); ++ j) {
            sum1 += a[pp[j + i * (n / m)]];
        }
        ans1 += (((aver - sum1) * (aver - sum1)) / m);
    }
    return ans1;
}

double RAND() {
    return (double)rand() / RAND_MAX;
}

int main() {
    
    srand(time(NULL));
    srand(114514);
    srand(1919810);
    srand(rand() + 19260817);
    srand(rand() + 20070111);
    srand(rand());
    
    cin >> n >> m;
    
    for(int i = 1; i <= n; ++ i) {
        cin >> a[i];
        p[i] = i;
        pp[i] = i;
        aver += a[i];
    }
    
    aver /= m;
    
    ans = sum();
    
    while((clock() / (1.0 * CLOCKS_PER_SEC)) <= 0.996) {
        double now = ans;
        for(int i = 1; i <= n; ++ i) {
            pp[i] = p[i];
        }
        double t = 3000;
        while(t > endt) {
            int x, y;
            do {
                x = Rand(1, n);
                y = Rand(1, n);
            }while(x == y) ;
            swap(pp[x], pp[y]);
            now = sum();
            if(now <= ans) ans = now;
            else if((1.0 * exp(ans - now)) / t <= RAND()) {
                swap(pp[x], pp[y]);
            }
            t *= down;
        }
    }
    
    printf("%.2lf", ans);
    
    return 0;
}
2022/10/1 18:28
加载中...