首页 > 代码库 > CodeVS 1344 线型网络
CodeVS 1344 线型网络
Sol
随机化算法+哈密顿路径.
好厉害的题...首先都会想到状压DP对吧,复杂度 \(O(n^2 2^n)\) .
\(n=20\) exm?? \(10^8\)
有一种算法就是随机化算法 再调整.
通过随机化算法,再 \(O(n^2)\) 来调整.
调整方式如下:
如果有 \(dis(i-1,i)+dis(j,j+1)>dis(i-1,j)+dis(i,j+1)\)
那么就将区间 \([i,j]\) 翻转...
非常神奇吧 关于证明原文中并没有,总之这样会导致很多不同的方案收束到同一方案,造成方案数的减少,来以随机概率获得正确结果.
PS:简直就是骗分神奇的方法...
原文链接:http://www.doc88.com/p-772451936672.html
Code
#include<cstdio>#include<cmath>#include<ctime>#include<utility>#include<cstdlib>#include<algorithm>#include<iostream>using namespace std;const int N = 25;#define mpr(a,b) make_pair(a,b)#define sqr(x) ((x)*(x))int n,T;pair<int,int> p[N];int a[N];double d[N][N];double ans=9999999999.0;inline int in(int x=0,char ch=getchar(),int v=1){ while(ch!=‘-‘&&(ch>‘9‘||ch<‘0‘)) ch=getchar();if(ch==‘-‘) v=-1,ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*v; }double dis(int u,int v){ return sqrt((double)sqr(p[u].first-p[v].first)+sqr(p[u].second-p[v].second)); }int main(){ srand(time(0)); n=in(); for(int i=1;i<=n;i++) p[i]=mpr(in(),in()),a[i]=i; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) d[i][j]=dis(i,j); // for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) printf("%.2lf%c",d[i][j]," \n"[j==n]);// for(int i=1;i<=n;i++) cout<<p[i].first<<" "<<p[i].second<<endl; for(T=2000;T--;){ random_shuffle(a+1,a+n+1); double tmp=0; // cout<<"***********"<<endl;// for(int i=1;i<=n;i++) cout<<a[i]<<" ";cout<<endl; for(int i=1;i<n;i++) for(int j=i+1;j<=n;j++) if(d[a[i-1]][a[i]]+d[a[j]][a[j+1]]>d[a[i-1]][a[j]]+d[a[i]][a[j+1]]) reverse(a+i,a+j+1); for(int i=1;i<n;i++) tmp+=d[a[i]][a[i+1]]; // cout<<"***********"<<endl;// for(int i=1;i<=n;i++) cout<<a[i]<<" ";cout<<endl;// cout<<"tmp="<<tmp<<endl; ans=min(ans,tmp); }printf("%.2lf\n",ans); return 0;}
CodeVS 1344 线型网络
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。