其他分享
首页 > 其他分享> > 模拟退火模板

模拟退火模板

作者:互联网

考前必看!!1

[NOIP2021] 方差

#include <bits/stdc++.h>

#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
#define rep(i, x, y) for (int i = (x); i <= (y); i+=1)
#define epr(i, x) for (int i = head[x]; i; i = nxt[i])
#define per(i, x, y) for (int i = (x); i >= (y); i-=1)
#define DC int T = gi <int> (); while (T--)
#define Add(a, b) a = (a + b) % mod
#define chkmin(a, b) a = min(a, b)
#define chkmax(a, b) a = max(a, b)
#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int, int> PII;
typedef pair <LL, int> PLI;
typedef pair <int, LL> PIL;
typedef pair <LL, LL> PLL;

template <typename T>
inline T gi()
{
	T x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f * x;
}

const int N = 10003, M = N << 1;
const double dlt = 0.9975, eps = 1e-14;

int n, a[N], b[N], cf[N];
LL ans = 1e18;

inline LL query()
{
	a[1] = 0;
	rep(i, 2, n) a[i] = a[i - 1] + cf[i];
	LL res = 0, tmp = 0;
	rep(i, 1, n) res += 1ll * a[i] * a[i], tmp += a[i];
	tmp = 1ll * tmp * tmp;
	res = 1ll * res * n - tmp;
	return res;
}

inline void SA()
{
	double T = 1000;
	while (T > eps)
	{
		if ((double)clock() / CLOCKS_PER_SEC > 0.993) {printf("%lld\n", ans); exit(0);}
		int x = rand() % (n - 2) + 3;
		swap(cf[x], cf[x - 1]);
		LL tans = query(), Dlt = tans - ans;
		if (Dlt < 0) ans = tans;
		else if (exp(-Dlt / T) * RAND_MAX <= rand()) swap(cf[x], cf[x - 1]);
		T *= dlt;
	}
}

int main()
{
	//freopen(".in", "r", stdin); freopen(".out", "w", stdout);
	srand(19491001); srand(rand()); srand(rand());
	n = gi <int> (); rep(i, 1, n) a[i] = gi <int> (), cf[i] = a[i] - a[i - 1];
	if (n == 1) return puts("0"), !!0;
	if (n == 2) return printf("%d\n", n * (a[1] * a[1] + a[2] * a[2]) - (a[1] + a[2]) * (a[1] + a[2])), !!0;
	while (1) SA();
	return !!0;
}

[JSOI2004] 平衡点 / 吊打XXX

#include <bits/stdc++.h>

#define DEBUG fprintf(stderr, "Passing [%s] line %d\n", __FUNCTION__, __LINE__)
#define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
#define rep(i, x, y) for (int i = (x); i <= (y); i+=1)
#define epr(i, x) for (int i = head[x]; i; i = nxt[i])
#define per(i, x, y) for (int i = (x); i >= (y); i-=1)
#define DC int T = gi <int> (); while (T--)
#define Add(a, b) a = (a + b) % mod
#define chkmin(a, b) a = min(a, b)
#define chkmax(a, b) a = max(a, b)
#define pb push_back
#define mp make_pair
#define fi first
#define se second

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int, int> PII;
typedef pair <LL, int> PLI;
typedef pair <int, LL> PIL;
typedef pair <LL, LL> PLL;

template <typename T>
inline T gi()
{
	T x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f * x;
}

const int N = 1003, M = N << 1;
const double dlt = 0.9975, eps = 1e-14;

int n;
int x[N], y[N], w[N];
double ansx, ansy, tx, ty, ans = 1e18;

inline double query(double xx, double yy)
{
	double res = 0;
	rep(i, 1, n)
	{
		double dx = xx - x[i], dy = yy - y[i];
		res += sqrt(dx * dx + dy * dy) * w[i];
	}
	return res;
}

inline void SA()
{
	double T = 2000;
	while (T > eps)
	{
		if ((double)clock() / CLOCKS_PER_SEC >= 0.993) {printf("%0.3lf %.3lf\n", ansx, ansy); exit(0);}
		double nx = tx + (rand() * 2 - RAND_MAX) * T, ny = ty + (rand() * 2 - RAND_MAX) * T;
		double tans = query(nx, ny), Dlt = tans - ans;
		if (Dlt < 0) ans = tans, ansx = tx = nx, ansy = ty = ny;
		else if (exp(-Dlt / T) * RAND_MAX > rand()) tx = nx, ty = ny;
		T *= dlt;
	}
}

int main()
{
	//freopen(".in", "r", stdin); freopen(".out", "w", stdout);
	srand(19491001); srand(rand()); srand(rand());
	n = gi <int> (); rep(i, 1, n) x[i] = gi <int> (), y[i] = gi <int> (), w[i] = gi <int> (), ansx += x[i], ansy += y[i];
	ansx /= n, ansy /= n;
	tx = ansx, ty = ansy;
	while (1) SA();
	printf("%.3lf %.3lf\n", ansx, ansy);
	return !!0;
}

标签:__,typedef,long,模拟退火,模板,pair,gi,define
来源: https://www.cnblogs.com/xsl19/p/Simulate-Anneal-templates.html