退火求调
  • 板块P3936 Coloring
  • 楼主baoziwu2
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/1/12 13:08
  • 上次更新2023/10/24 04:36:20
查看原帖
退火求调
418670
baoziwu2楼主2023/1/12 13:08

rt,分数稳定在 90pts ~ 99pts

就是上不到 100pts

是初解构造的太烂还是参数不行啊(

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <random>

using namespace std;
using pii = pair<int, int>;

random_device srd;
mt19937 gen(srd());

#define x first
#define y second

int const N = 25;

static const int dx[] = {1, -1, 0, 0};
static const int dy[] = {0, 0, 1, -1};

struct FSIO {
	template<typename types>
	FSIO operator >> (types &x) {
		x = 0; bool neg = false; char ch = getchar();
		while(!isdigit(ch)) {
			if(ch == '-') neg = true;
			ch = getchar();
		}
		while(isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
		x = neg ? -x : x; return *this;
	}
	
	template<typename types>
	FSIO operator << (types x) {
		static char buf[130]; int tot = 0;
		if(x < 0) putchar('-'), x = -x;
		if(!x) putchar('0');
		while(x) buf[tot] = x % 10 + '0', x /= 10, ++ tot;
		while(tot) -- tot, putchar(buf[tot]);
		return *this;
	}
	
	FSIO operator <<(bool x) {
		putchar(x ? '1' : '0');
		return *this;
	}
	
	FSIO operator << (char x) {
		putchar(x);
		return *this;
	}
	
	FSIO operator << (const char *x) {
		int len = strlen(x);
		for(int i = 0; i < len; ++ i) putchar(x[i]);
		return *this;
	}
	
} fio;

int n, m, c;
static int p[N];
int mp[N][N];
int cur; pii pcur;

inline int fstcalc() {
	int res = 0;
	
	for(int x = 1; x <= n; ++ x) 
		for(int y = 1; y <= m; ++ y) 
			for(int i = 0; i < 4; ++ i) {
		int nx = x + dx[i], ny = y + dy[i];
		if(nx > n || nx < 1 || ny > m || ny < 1) continue;
		res += (mp[x][y] != mp[nx][ny]);
	}
	
	return (res / 2);
}

inline int calc(int x1, int y1, int x2, int y2) {
	int res1 = 0;
	for(int i = 0; i < 4; ++ i) {
		int nx1 = x1 + dx[i], ny1 = y1 + dy[i], nx2 = x2 + dx[i], ny2 = y2 + dy[i];
		if(1 <= nx1 && nx1 <= n && 1 <= ny1 && ny1 <= m) res1 += (mp[x1][y1] != mp[nx1][ny1]);
		if(1 <= nx2 && nx2 <= n && 1 <= ny2 && ny2 <= m) res1 += (mp[x2][y2] != mp[nx2][ny2]);
	}
	
	swap(mp[x1][y1], mp[x2][y2]);
	int res2 = 0;
	for(int i = 0; i < 4; ++ i) {
		int nx1 = x1 + dx[i], ny1 = y1 + dy[i], nx2 = x2 + dx[i], ny2 = y2 + dy[i];
		if(1 <= nx1 && nx1 <= n && 1 <= ny1 && ny1 <= m) res2 += (mp[x1][y1] != mp[nx1][ny1]);
		if(1 <= nx2 && nx2 <= n && 1 <= ny2 && ny2 <= m) res2 += (mp[x2][y2] != mp[nx2][ny2]);
	}
	
	swap(mp[x1][y1], mp[x2][y2]);
	return res1 - res2;
}

inline pii lineToSq(int x) {
	if(x % m == 0) return pii{x / m, m};
	return pii{x / m + 1, x % m};
}

inline int sqToLine(pii t) {
	return (t.x - 1) * m + t.y; 
}

inline void sa() {
	for(double tem = 1e14; tem > 5e-7; tem *= 0.99997) {
		int t = gen() % (n * m) + 1; 
		pii pt = lineToSq(t), pcur = lineToSq(gen() % (n * m) + 1);
		/*if(mp[pt.x][pt.y] == 0 || mp[pcur.x][pcur.y] == 0) {
			cerr << pt.x << " " << pt.y << " " << pcur.x << " " << pcur.y << endl;
			exit(-1);
		}*/
		int derta = calc(pcur.x, pcur.y, pt.x, pt.y); // derta < 0 worse, derta > 0, better
		// if(derta == 1) cerr << (1.0 * derta / tem) << endl;
		if(exp(1.0 * derta / tem) >= 1.0) {
			// cerr << cur << " " << derta << endl;
			cur -= derta, swap(mp[pcur.x][pcur.y], mp[pt.x][pt.y]);
		}
	}
}

inline void output() {
	for(int i = 1; i <= n; ++ i) {
		for(int j = 1; j <= m; ++ j)
			fio << mp[i][j] << " ";
		putchar('\n');
	}
}

int main() {
    srand(time(NULL));
	fio >> n >> m >> c;
	for(int i = 1; i <= c; ++ i) fio >> p[i];
	
	int x = 0, y = 1;
	//mp[1][1] = mp[1][2] = 1; mp[1][3] = mp[2][3] = 2; mp[2][1] = mp[3][1] = mp[2][2] = mp[3][3] = mp[3][2] = 3;
	// output();
	
	for(int i = 1; i <= n; ++ i) {
		for(int j = 1; j <= m; ++ j) {
			if(++ x > p[y]) x = 1, ++ y;
			mp[i][j] = y;
		}
	}
	//output();
	
	//mp[1][1] = mp[2][1] = 2, mp[1][2] = mp[2][2] = mp[2][3] = 3, mp[1][3] = 1;
	
	cur = fstcalc(), pcur = {1, 1};
	while((double)clock() / CLOCKS_PER_SEC < 4.7) sa();
	
	output();
	
	//cerr << fstcalc() << endl;
	return 0;
}
2023/1/12 13:08
加载中...