模拟退火球调
查看原帖
模拟退火球调
519384
Link_Cut_Y楼主2022/7/8 17:19
#include <iostream>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <algorithm>
#include <cmath>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;
const int N = 1010, INF = 0x3f3f3f3f;
int n, m, len;
int w[N][N], res = INF;

int rand(int l, int r)
{
	return rand() / RAND_MAX * (r - l) + l;
}

int calc(PII pos)
{
    int cntmax = -INF, cntmin = INF;
    for (int i = pos.x - len + 1; i <= pos.x; i ++ )
        for (int j = pos.y - len + 1; j <= pos.y; j ++ )
            cntmax = max(cntmax, w[i][j]),
            cntmin = min(cntmin, w[i][j]);
            
    res = min(res, cntmax - cntmin);
    return cntmax - cntmin;
}

void simulate_anneal()
{
    PII x(rand(1, n), rand(1, m));
    
    for (int t = 1000; t >= 0.1; t *= 0.99)
    {
        int f1 = calc(x);
        PII y(rand(x.x - (int)(t * 10), x.x + (int)(t * 10)), rand(x.x - (int)(t * 10), x.x + (int)(t * 10)));
        if (y.x <= 0 || y.y <= 0 || y.x > n || y.y > m) continue;
        	
        int f2 = calc(y);
        int delta = f2 - f1;
        if (exp( - delta / t) > rand() / RAND_MAX) x = y;
    }
}

int main()
{
    srand(time(0));
    
    scanf("%d%d%d", &n, &m, &len);
    
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            scanf("%d", &w[i][j]);
            
    while (clock() / CLOCKS_PER_SEC <= 0.97) 
        simulate_anneal();
        
    printf("%d\n", res);
    
    return 0;
}
2022/7/8 17:19
加载中...