这种答案跟序列排列顺序有关的,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 }