求助模拟退火部分RE
查看原帖
求助模拟退火部分RE
567054
Catium楼主2022/5/20 22:08

只有前49分的7个点没RE,数组已经开大100倍了也不行(
RE记录


#include <cmath>
#include <iostream>
using namespace std;
/*
Красная Армия всех сильней.
*/
void pre() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
#define DEBUG(A) cout << A << endl
#else
#define DEBUG(A)
#endif
}

#define N 2002000
#define down 0.9996
#define eps 1e-10

int n;
int w[N];
int d[N];     // i~i+1的距离
int dsum[N];  // d的前缀和,从山顶i + 1的距离,那么i~j的距离就是(dsum[j] - dsum[i])
int x1, x2;   //全局最优解,显然一定是某棵树的下标
int ans;      //全局最优答案
void sa() {
    for (double T = 10000; T > eps; T *= down) {
        int nx1, nx2;
        nx1 = ((int)(x1 + (rand() * 2 - RAND_MAX) * T) % n) + 1;
        nx2 = ((int)(x2 + (rand() * 2 - RAND_MAX) * T) % n) + 1;
        if (nx1 > nx2) {
            swap(nx1, nx2);
        }
        int nans = 0;
        for (int i = 1; i <= nx1; i++) {
            nans += (dsum[nx1] - dsum[i]) * w[i];
        }
        for (int i = nx1 + 1; i <= nx2; i++) {
            nans += (dsum[nx2] - dsum[i]) * w[i];
        }
        for (int i = nx2 + 1; i <= n; i++) {
            nans += (dsum[n + 1] - dsum[i]) * w[i];
        }
        int dans = nans - ans;
        if (dans < eps) {
            ans = nans;
            x1 = nx1;
            x2 = nx2;
        } else {
            if (exp(-dans / T) * RAND_MAX > rand()) {
                ans = nans;
                x1 = nx1;
                x2 = nx2;
            }
        }
    }
}

signed main() {
    pre();
    /*code here*/
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> w[i] >> d[i];
        dsum[i + 1] = dsum[i] + d[i];
    }
    x1 = n / 3;
    x2 = x1 * 2;
    for (int i = 1; i <= x1; i++) {
        ans += (dsum[x1] - dsum[i]) * w[i];
    }
    for (int i = x1 + 1; i <= x2; i++) {
        ans += (dsum[x2] - dsum[i]) * w[i];
    }
    for (int i = x2 + 1; i <= n; i++) {
        ans += (dsum[n + 1] - dsum[i]) * w[i];
    }
    sa();
    cout << ans;
    return 0;
}

2022/5/20 22:08
加载中...