记录编号 119106 评测结果 AAAATTTTTA
题目名称 线型网络 最终得分 50
用户昵称 Gravatarcstdio 是否通过 未通过
代码语言 C++ 运行时间 8.633 s
提交时间 2014-09-11 11:32:19 内存使用 1.06 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define sqr(x) (x)*(x)
const int SIZEN=21,SIZEP=4050;
const double INF=1e9;
int N;
double x[SIZEN]={0},y[SIZEN]={0};
double dist(int a,int b){
	return sqrt(sqr(x[a]-x[b])+sqr(y[a]-y[b]));
}
int bigrand(void){
	return ((rand()<<15)|rand())&0x7fffffff;
}
int random(int x,int y){
	return bigrand()%(y-x+1)+x;
}
void random_permute(int *s){
	for(int i=1;i<=N;i++) s[i]=i;
	for(int i=1;i<=N;i++) swap(s[i],s[random(i,N)]);
}
class CYCLE{
public:
	int s[SIZEN];
	double len;//长度
	void calc_len(void){
		len=0;
		for(int i=1;i<N;i++) len+=dist(s[i],s[i+1]);
	}
	void mutation(void){//变异
		int i=random(1,N);
		int j=random(i,N);
		while(i<j){
			swap(s[i],s[j]);
			i++,j--;
		}
	}
	void mating(CYCLE &b,int l,int r){//b送给它一段祖传的染色体......
		int atp[SIZEN]={0};
		for(int i=1;i<=N;i++) atp[s[i]]=i;
		for(int i=l;i<=r;i++){
			if(s[i]!=b.s[i]){
				atp[s[i]]=atp[b.s[i]];
				swap(s[i],s[atp[b.s[i]]]);
				atp[b.s[i]]=i;
			}
		}
	}
};
int P=400;
CYCLE A[SIZEP],B[SIZEP];
CYCLE ans;
double f[SIZEP]={0};
void select(void){//自然选择,把B选到A,此时B已经计算出了len
	double mx=0;
	for(int i=1;i<=P;i++) mx=max(mx,B[i].len);
	double sum=0;
	for(int i=1;i<=P;i++) f[i]=mx*1000.0/B[i].len,sum+=f[i];
	int tot=0;
	for(int i=1;i<=P;i++){
		int tmp=(f[i]/sum)*(P+0.0)+0.5;
		while(++tot<=N&&tmp--) A[tot]=B[i];
	}
}
void multiply(void){//繁殖,把A繁殖到B,并计算B的len,用它更新答案
	double mxl=INF;int mxid;
	for(int i=1;i<=P;i++){
		if(A[i].len<mxl) mxl=A[i].len,mxid=i;
		B[i]=A[i];
	}
	for(int i=1;i<P;i+=2){//梅亭,不对,mating
		int l=random(1,N),r=random(l,N);
		B[i].mating(A[i+1],l,r);
		B[i+1].mating(A[i],l,r);
	}
	int vp=10;//变异概率的倒数
	for(int i=1;i<=P;i++) if(random(1,vp)==1) B[i].mutation();//变异
	for(int i=1;i<=P;i++){//更新答案
		B[i].calc_len();
		if(B[i].len<ans.len) ans=B[i];
	}
	for(int i=1;i<=P;i++) if(A[i].len<B[i].len) B[i]=A[i];//子比父强优化
	if(A[mxid].len<B[mxid].len) B[mxid]=A[mxid];//精英主义优化
	//B[1]=mx;
}
void GA(void){//遗传算法
	int gtot=10000;//传代次数
	ans.len=INF;
	for(int i=1;i<=P;i++){
		random_permute(A[i].s);
		A[i].calc_len();
		if(A[i].len<ans.len) ans=A[i];
	}
	for(int i=1;i<=gtot;i++){
		multiply();
		select();
	}
}
void read(void){
	scanf("%d",&N);
	for(int i=1;i<=N;i++) scanf("%lf%lf",&x[i],&y[i]);
}
int main(void){
	freopen("linec.in","r",stdin);
	freopen("linec.out","w",stdout);
	//srand(time(0));
	read();
	GA();
	printf("%.2lf\n",ans.len);
	return 0;
}