Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P2210 Haywire

P2210 Haywire

死活过不了 #7 ,在巨佬 $@lucky叶$ 的帮助下,随机打乱初始数组即可过。一定要记住,模拟退火的初始状态一定要是随机的,刚学模拟退火,代码很丑。

查看代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <cstdio>
#include <ctime>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 15;
bool frd[N][N];
int n, mn = 500, cur, pos[N];
int rd(int l, int r)
{
return rand() % (r - l) + l;
}
double rd(double l, double r)
{
return (double)rand() / RAND_MAX * (r - l) + l;
}
int cal()
{
int res = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (frd[i][j])
res += abs(pos[i] - pos[j]);
mn = min(mn, res / 2);
return res / 2;
}
void SimulateAnneal()
{
for (int i = 1; i <= n; i++)
pos[i] = i;
random_shuffle(pos + 1, pos + n + 1);
for (double t = 1e4; t > 1e-2; t *= 0.996)
{
int x = rd(1, n), y = rd(1, n);
while (x == y)
x = rd(1, n), y = rd(1, n);
cur = cal();
swap(pos[x], pos[y]);
int delta = cal() - cur;
if (exp(-delta / t) <= rd(0.0, 1.0))
swap(pos[x], pos[y]);
}
}
int main()
{
srand(time(NULL));
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1, a; j <= 3; j++)
{
scanf("%d", &a);
frd[i][a] = true;
}
while ((double)clock() / CLOCKS_PER_SEC < 0.9)
SimulateAnneal();
printf("%d\n", mn);
return 0;
}