#include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>#define MaxGen       30
#define chrom_length 4
#define PopSize     20
#define Upper_Num     5
#define Down_Num      6
#define Point_Num     11
#define INFINITY      9999
#define pc     0.6
#define pm      0.05   
#define E  2.78  
       
double best=INFINITY;
double d=2,l=10;
double weight=0.5;
int gen;struct individual
{
int chrom[chrom_length];
    double value;
    double fitness;//评价
};
struct Point
{
double x;
    double y;
}m_point[Point_Num]={{0,0},{d,0},{2*d,0},{3.5*d,0},{5*d,0},{2*d,l},{3*d,l},{4*d,l},{0,l+d},{d,l+d},{5*d,l+d}};int Best[chrom_length];struct individual population[PopSize];double Upper_Array[Upper_Num][35]={
    4,3,2,3,4,4,3,1,3,4,2,1,0,1,2,3.5,5,17,15,15,
    14,12,13,13,15,9,10,11,12,13,13,11,13,10,12,5,
    4,3,4,5,5,4,2,2,3,3,2,1,0,1,2.5,4,16,14,14,13,
    11,12,12,14,8,9,10,11,12,12,10,12,9,11,6,5,4,
    5,4,6,5,3,3,2,4,3,2,1,0,1.5,3,15,13,13,17,10,
    11,11,13,7,8,9,10,11,11,9,11,8,10,7.5,6.5,5.5,
    6.5,5.5,7.5,6.5,4.5,4.5,3.5,5.5,4.5,3.5,2.5,1.5,
    0,1.5,13.5,11.5,11.5,10.5,8.5,9.5,9.5,11.5,5.5,
    6.5,7.5,8.5,9.5,9.5,7.5,9.5,6.5,8.5,9,8,7,6,5,9,
    8,6,6,5,7,6,5,4,3,1.5,0,12,10,10,9,7,8,8,10,4,5,
    6,7,8,8,6,8,5,7
};
double Down_Array[Down_Num][12]=
{
0,2,4,4,3,2,3,4,5,8.47214,8,6,
    2,0,2,5,4,3,2,3,4,9.47214,9,7,
    4,2,0,6,5,4,3,2,3,10.47214,10,8,
    4,5,6,0,1,2,3,4,5,4.47214,4,2,
    3,4,5,1,0,1,2,3,4,5.47214,5,3,
    5,4,3,5,4,3,2,1,0,9.47214,9,7
};
int murr(int n)
{
int i,sum=1;
    for(i=n;i>0;i--)sum*=i;
return sum;
}//求n!double min(double x,double y)
{
    return (x>y?y:x);
}
double length(double x1,double y1,double x2,double y2)
{
return (sqrt(pow((x1-x2),2)+pow((y1-y2),2)));
}//两点间距离
double max(double x,double y)
{
return(x>y?x:y);
} void Gener_Init(){//初始化
   int i,j;
   for(i=0;i<PopSize;i++)
   {
      do{     for(j=0;j<chrom_length;j+=2)
                population[i].chrom[j]=rand()%5;
}while(population[i].chrom[0]==population[i].chrom[2]);
      do{
      for(j=1;j<chrom_length;j+=2)
         population[i].chrom[j]=rand()%6;
      }while(population[i].chrom[1]==population[i].chrom[3]);
   }
}void Add_Value(){//目标函数
   int i,j,t1,t2,t3,t4;
   double Umin_Value,Dmin_Value;
   double l1,l2;
   for(i=0;i<PopSize;i++){
      Umin_Value=0;  Dmin_Value=0;
      for(j=0;j<35;j++)
       Umin_Value+=min(Upper_Array[population[i].chrom[0]][j],
       Upper_Array[population[i].chrom[2]][j]);
      for(j=0;j<12;j++)
       Dmin_Value+=min(Down_Array[population[i].chrom[1]][j],
           Down_Array[population[i].chrom[3]][j]);      t1=population[i].chrom[0];
      t2=population[i].chrom[1]+5;
      t3=population[i].chrom[2];
      t4=population[i].chrom[3]+5;
      l1=length(m_point[t1].x,
                m_point[t1].y,
                m_point[t2].x,
                m_point[t2].y);      l2=length(m_point[t3].x,
                m_point[t3].y,
                m_point[t4].x,
                m_point[t4].y);      population[i].value=weight*(Umin_Value+Dmin_Value)+(1-weight)*(l1+l2)*100;
   }
}
void selection(){//选择
   int i,index;
   double p,temp=0,total=0;
   double cfitness[PopSize];
   struct individual newpopulation[PopSize];   for(i=0;i<PopSize;i++){
      temp=max(population[i].value,temp);
       total+=population[i].value; 
   }  temp+=100;   for(i=0;i<PopSize;i++){
      population[i].fitness=(temp-population[i].value)/(PopSize*temp-total);
      cfitness[i]=population[i].fitness;
      }
   for(i=1;i<PopSize;i++)
      cfitness[i]+=cfitness[i-1];
   for(i=0;i<PopSize;i++){
      p=rand()%1000/1000.0;
      index=0;
      while(p>cfitness[index])
         index++;
      newpopulation[i]=population[index];
   }
   for(i=0;i<PopSize;i++){
      population[i]=newpopulation[i];
   }
}
void  Crossing(){//交叉
   int i,j;//
   int index[PopSize],temp,point;
   double p;
   for(i=0;i<PopSize;i++)
      index[i]=i;
   for(i=0;i<PopSize;i++){
      point=rand()%(PopSize-i);
      temp=index[i];
      index[i]=index[point+i];
      index[point+i]=temp;
   }
   for(i=0;i<PopSize;i+=2){
      p=rand()%1000/1000.0;
      if(p<pc){
         point=rand()%2;
         if(point==0)
             for(j=0;j<chrom_length;j+=2)
          {
             temp=population[index[i]].chrom[j];
             population[index[i]].chrom[j]
                =population[index[i+1]].chrom[j];
             population[index[i+1]].chrom[j]=temp;
          }
         else 
         for(j=1;j<chrom_length;j+=2)
          {
             temp=population[index[i]].chrom[j];
             population[index[i]].chrom[j]
                =population[index[i+1]].chrom[j];
             population[index[i+1]].chrom[j]=temp;
          }
      }
   }
}
void Muta_Opeator(){//
   int i,j,s,q;
   double p;
   for(i=0;i<PopSize;i++)
      for(j=0;j<chrom_length;j++){
         p=rand()%1000/1000.0;
         if(p<pm){
             q=rand()%4;
         switch(q){
         case 0:   
             s=rand()%5;
             while(s==population[i].chrom[2])
                s=rand()%5;
               population[i].chrom[q]=s;
               break;
         case 1:
             s=rand()%6;
             while(s==population[i].chrom[3])
                s=rand()%6;
               population[i].chrom[q]=s;
               break;
         case 2:
             s=rand()%5;
             while(s==population[i].chrom[0])
                s=rand()%5;
               population[i].chrom[q]=s;
               break;
         case 3:
             s=rand()%6;
             while(s==population[i].chrom[1])
                s=rand()%6;
               population[i].chrom[q]=s;
               break;
          }
      }
   }

void print(){
   int i,temp=-1;
   double average,sum=0;
   cout<<endl;
   for(i=0;i<PopSize;i++)
      sum+=population[i].value;
   average=sum/PopSize;
   for(i=0;i<PopSize;i++){
      if(best>=population[i].value){
         best=population[i].value;
         temp=i;
      }
   }
   if(temp!=-1){
   for(i=0;i<chrom_length;i++)
      Best[i]=population[temp].chrom[i];
   }
   cout<<"Generation="<<gen<<"  Average="<<average
      <<"  Best_Value="<<best<<endl;
   cout<<"Best_Chrom";
   for(i=0;i<chrom_length;i++)
      cout<<Best[i]<<" "; 
   cout<<endl;
}
void main(){
   int q=5,k;
   double p[35],sum;
   int i,j;
   do{
     for(i=0;i<35;i++){
       k=rand()%(3*q);
       p[i]=pow(q,k)*pow(E,-1*q)/(murr(k));
       sum+=p[i];}
   }while(sum==1.0);//生成随机数求权重数组p[i]
   for(i=0;i<Upper_Num;i++)
      for(j=0;j<35;j++)
         Upper_Array[i][j]*=p[j];        
      do{
      for(i=0;i<12;i++){
       k=rand()%(3*q);
       p[i]=pow(q,k)*pow(E,-1*q)/(murr(k));
       sum+=p[i];}
   }while(sum==1.0);
   for(i=0;i<Down_Num;i++)
      for(j=0;j<12;j++)
         Down_Array[i][j]*=p[j];
   gen=0;
   Gener_Init();
   while(gen<MaxGen){
        Add_Value();
      print();
      selection();
      Crossing();
      Muta_Opeator();
   //   print();
      gen++;
   }
}