模拟退火,WA54pts
查看原帖
模拟退火,WA54pts
511676
naoliaok_lovely楼主2023/10/7 18:38
#include<bits/stdc++.h>
using namespace std;
mt19937 rd(time(0));

const int N = 50;
int n, a[N], l[N], r[N], d[N][2][N][2];
int w[N], ans, res;

inline double rand(double l, double r)
{
	return 1.0 * rand() / RAND_MAX * (r - l) + l;
}

inline int get()
{
	int res = 0;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j < i; j++)
			res += d[j][w[j]][i][w[i]];
	ans = min(ans, res);
	return res;
}
inline int get(int x)
{
	int delta = 0;
	for(int i = 1; i <= n; i++)
		delta += d[x][!w[x]][i][w[i]] - d[x][w[x]][i][w[i]];
	ans = min(ans, res + delta);
	return delta;
}

void SA()
{
	for(int i = 1; i <= n; i++)
		w[i] = rd() & 1;
	res = get();
	
	for(double t = 1e2; t >= 1e-3; t *= 0.999)
	{
		int x = rd() % n + 1, d = get(x);
		if(exp(-d / t) > rand(0, 1)) res += d, w[x] ^= 1;
	}
}

int main()
{
	srand(time(0));
	
	int T;
	cin >> T;
	for(int T1 = 1; T1 <= T; T1++)
	{
		memset(l, 0, sizeof(l));
		memset(r, 0, sizeof(r));
		memset(d, 0, sizeof(d));
		ans = 1e9;
		
		cin >> n;
		for(int i = 1; i <= n; i++)
		{
			scanf("%d", &a[i]);
			if(!l[a[i]]) l[a[i]] = i;
			else r[a[i]] = i;
		}
		for(int i = 1; i <= n; i++)
			for(int j = 1; j < i; j++)
				if(r[i] && r[j])
				{
					if(l[i] < l[j] && r[j] < r[i])
						d[l[j]][0][r[j]][1]++, d[l[j]][1][r[j]][0]++, d[r[j]][0][l[j]][1]++, d[r[j]][1][l[j]][0]++;
					else if(l[j] < l[i] && r[i] < r[j])
						d[l[i]][0][r[i]][1]++, d[l[i]][1][r[i]][0]++, d[r[i]][0][l[i]][1]++, d[r[i]][1][l[i]][0]++;
					else if(l[i] < l[j] && l[j] < r[i] && r[i] < r[j]) 
						d[l[j]][0][r[i]][0]++, d[l[j]][1][r[i]][1]++, d[r[i]][0][l[j]][0]++, d[r[i]][1][l[j]][1]++;
					else if(l[j] < l[i] && l[i] < r[j] && r[j] < r[i])  
						d[l[i]][0][r[j]][0]++, d[l[i]][1][r[j]][1]++, d[r[j]][0][l[i]][0]++, d[r[j]][1][l[i]][1]++;
				}
		
		while(1.0 * clock() / CLOCKS_PER_SEC <= 0.019 * T1) SA();
		cout << ans << endl;
	}
	return 0;
}

2023/10/7 18:38
加载中...