这种答案跟序列排列顺序有关的,n比较小的(稍微大一点的也可以),求最优解的,一般都可以随机化过

随机化不一定是模拟退火或是什么遗传蚁群

哪怕只是直接随机化一个序列,只要你随机的次数够多,它都能找到正解

——沃·兹基硕德

不久前还看到一个斜率优化的题目,有人用二重循环A掉,原因竟是第二重循环只在前500个元素中寻找最优解...然后就切掉了....

所以这道题的解法很明显了呀...

用退火的板子,但根本不用调参...

相当于就是在暴力的随机版本...随便找几个解的情况判断可行性

没想到交了两次就过了(91-->100)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<ctime>
 7 using namespace std;
 8 inline int read(){
 9     char chr=getchar();    int f=1,ans=0;
10     while(!isdigit(chr)) {if(chr=='-') f=-1;chr=getchar();}
11     while(isdigit(chr))  {ans=(ans<<3)+(ans<<1);ans+=chr-'0';chr=getchar();}
12     return ans*f;
13 }
14 void write(int x){
15     if(x<0) putchar('-'),x=-x;
16     if(x>9) write(x/10);
17     putchar(x%10+'0');
18 }int n,a[20][4],p[20]={0,6, 5, 1, 4, 2, 3},ans,q[20],o[20];
19 int getans(){
20     int ans=0;
21     for(int i=1;i<=n;i++)
22         o[p[i]]=i;
23     for(int i=1;i<=n;i++){
24         int x=a[i][1],y=a[i][2],z=a[i][3];
25         ans+=abs(o[x]-o[i]);
26         ans+=abs(o[y]-o[i]);
27         ans+=abs(o[z]-o[i]);
28     }return ans;    
29 }
30 int random(int x){return rand()%x+1;}
31 void Fire(){
32     double T=1926.0;
33     while(T>1e-14){
34         int x=random(n),y=random(n);
35         swap(p[x],p[y]);
36         int tans=getans();
37         double DE=tans-ans;
38         if(DE<0){ans=tans;for(int j=1;j<=n;j++)q[j]=p[j];}
39         T*=0.999;
40 //        cout<<T<<endl;
41     }
42 } 
43 int main(){
44     srand(unsigned(time(0)));
45     n=read();
46     for(int i=1;i<=n;i++)a[i][1]=read(),a[i][2]=read(),a[i][3]=read(),p[i]=i;
47     ans=getans();
48     for(int i=1;i<=55;i++) Fire();
49     cout<<ans/2;
50     return 0;
51 }