模拟退火——模板
题目背景为TSP。
View Code
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<cmath>
6 #include<ctime>
7
8 using namespace std;
9
10 const int maxn=100;
11 const double max_t=10000.0;
12 const double ratio=0.98;
13 const double eps=1e-6;
14 const int per_t=25;
15 const int tT=1;
16
17 int n;
18
19 int ans;
20
21 bool use[maxn];
22
23 int map[maxn][maxn];
24
25 int z[maxn],y[maxn];
26
27 void calc()
28 {
29 for (int T=1;T<=tT;T++)
30 {
31 memset(use,false,sizeof(use));
32 use[0]=true;
33 long long nowans=0;
34 use[1]=true;
35 z[1]=1;
36 for (int a=2;a<=n;a++)
37 {
38 int wx=0;
39 while (use[wx])
40 wx=rand()%n+1;
41 z[a]=wx;
42 use[wx]=true;
43 nowans+=map[z[a-1]][z[a]];
44 }
45 nowans+=map[z[n]][z[1]];
46 for (double nowt=max_t;nowt>=eps;nowt*=ratio)
47 {
48 for (int hehe=1;hehe<=per_t;hehe++)
49 {
50 int nowp1=rand()%(n-1);
51 int nowp2=rand()%(n-1);
52 while (nowp1==nowp2)
53 {
54 nowp1=rand()%(n-1);
55 nowp2=rand()%(n-1);
56 }
57 nowp1+=2;nowp2+=2;
58 if (nowp1>nowp2) swap(nowp1,nowp2);
59 long long newans=0;
60 swap(z[nowp1],z[nowp2]);
61 for (int a=1;a<n;a++)
62 newans+=map[z[a]][z[a+1]];
63 newans+=map[z[n]][z[1]];
64 long long delta=nowans-newans;
65 if (newans<nowans || exp((double)delta/nowt)>rand()/RAND_MAX)
66 {
67 nowans=newans;
68 }
69 else swap(z[nowp1],z[nowp2]);
70 if (ans>nowans)
71 {
72 for (int a=1;a<=n;a++)
73 y[a]=z[a];
74 ans=nowans;
75 }
76 }
77 }
78 }
79 }
80
81 int main()
82 {
83 scanf("%d",&n);
84 if (n==1)
85 {
86 printf("0\n");
87 return 0;
88 }
89 for (int a=1;a<=n;a++)
90 for (int b=1;b<=n;b++)
91 scanf("%d",&map[a][b]);
92 ans=123456789;
93 srand(time(0));
94 calc();
95 printf("%d\n",ans);
96 for (int a=1;a<=n;a++)
97 {
98 printf("%d",y[a]-1);
99 if (a==n) printf("\n");
100 else printf(" ");
101 }
102
103 return 0;
104 }