//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Mexico.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma resource "*.dfm"
TForm1 *Form1;

const KolReisMax=15;  //кол-во рейсов
//const q=60;       //минут в часе :)
int TW[KolReisMax][KolReisMax];  //Таблица номер 3.
unsigned WaitMin; //заведомо очень большое число ;)
int IndOptim[KolReisMax];         //оптимальный вариант
int KolReis;




//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormCreate(TObject *Sender)
{
 int i;
 char abr ='a';
 for (i=0;i< GridMA->ColCount; i++)
 {
 GridMA->Cells[i][0] = IntToStr(i+1);
 GridMA->Cells[i][1] = " ";
 char ab=abr+i;
 GridAM->Cells[i][0] = ab;
 GridAM->Cells[i][1] = " ";
 }
 GridRez->Cells[0][0]="Отпр";
 GridRez->Cells[1][0]="Возвр";
 LoadClick(NULL);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BtnStartClick(TObject *Sender)
{
  WaitMin=1440*KolReisMax;
  KolReis=EditKol->Text.ToInt();
  clear();
  int OtM[KolReisMax];
  int OtA[KolReisMax];
  try
   {
  for (int i=0;i<KolReis;i++)
        {
        if(GridMA->Cells[i][1]==" "||GridAM->Cells[i][1]==" ") {error();return;}
        OtM[i]=StrToFloat(GridMA->Cells[i][1])*60;
        OtA[i]=StrToFloat(GridAM->Cells[i][1])*60;
        }
   }
  catch (...)
   {
   error();
   return;
   }

  int TimeP=360; //время поездки
//-----------первая таблица---------------
int TablAM[KolReisMax][KolReisMax];
int IndFirstJ=-1;                 //индекс начала записи в таблицу
for (int i=0;i<KolReis;i++)
 {
        //cout << endl;
        bool f=0;
        int n=0;
        for (int j=0;j<=2*KolReis;j++)
        {
                 int TimeAkk=OtA[i]+TimeP;
                 int TimeMex;
                 if (j>=KolReis) TimeMex=1440+OtM[j-KolReis];
                        else TimeMex=OtM[j];
                 int TimeWait;
                 TimeWait=TimeMex-TimeAkk;
                 if (j==IndFirstJ) f=1;
                 if (n<KolReis&&(TimeWait>=240&&TimeWait<=1440||f))
                 {
                 TablAM[i][n]=TimeWait;
                 if (f==0) {f=1;IndFirstJ=j;}
                 if (TimeWait<240) TablAM[i][n]=0;
                 //cout << TablAM[i][n]<< " ";
                 n++;
                 }
        }
 }
//-------- вторая таблица ------------------
int TablMA[KolReisMax][KolReisMax];
for (int i=0;i<KolReis;i++)
 {
        for (int j=IndFirstJ;j<IndFirstJ+KolReis;j++)
        {
         int TimeAkk;
         if (j>=KolReis) TimeAkk=1440+OtM[j-KolReis]+TimeP;
                 else TimeAkk=OtM[j]+TimeP;
         int TimeMex=1440+OtA[i];
         int TimeWait;
                 TimeWait=TimeMex-TimeAkk;
         if (TimeWait>=240) TablMA[i][j-IndFirstJ]=TimeWait;
                 else TablMA[i][j-IndFirstJ]=0;
        }
 }
//--------третья таблица,как наименьшее из 1-й и 2-й и !=0---------------------
char abr ='a';
for (int i=0;i<KolReis;i++)
 {
        for (int j=0;j<KolReis;j++)
        {
         if((TablMA[i][j]<TablAM[i][j]&&TablMA[i][j]!=0)||TablAM[i][j]==0)
                TW[i][j]=TablMA[i][j];
         else   TW[i][j]=TablAM[i][j];
         GridTW->Cells[i+1][j+1]=TW[i][j];
         GridTW->Cells[i+1][0]=i+1;
         char ab=abr+IndFirstJ+i;
         if (ab>'a'+KolReis-1) ab-=KolReis;
         GridTW->Cells[0][i+1]=ab;
        }
 }
//-------
int index[KolReisMax];
for (int i=0;i<KolReis;i++)index[i]=i;

if(TablAM[0][1]<=TablMA[0][1]) search(KolReis,index);
 else
 {
 WaitMin=0;
 for(int i=0;i<KolReis;i++){IndOptim[i]=i;
        WaitMin+=TW[i][i]; }
 }
char First[KolReisMax];
char Second[KolReisMax];
for (int i=0;i<KolReis;i++)
 {
   int j=IndOptim[i];
   if (TW[i][j]==TablMA[i][j])
        {
         First[i]='a'+IndFirstJ+j;
         if (First[i]>'a'+KolReis-1) First[i]-=KolReis;
         Second[i]='1'+i;
        }
   else
        {
         First[i]='1'+i;
         Second[i]='a'+IndFirstJ+j;
         if (Second[i]>'a'+KolReis-1) Second[i]-=KolReis;
        }
   if (First[i]>='a')  GridRez->Cells[0][i+1]=First[i];
        else GridRez->Cells[0][i+1]=StrToInt(i+1);
   if (Second[i]>='a') GridRez->Cells[1][i+1]=Second[i];
        else GridRez->Cells[1][i+1]=StrToInt(i+1);
 }
LabeledEdit->Text=IntToStr(WaitMin)+"="+FloatToStr(WaitMin/60)+" часа(ов)";


}


//-------------функция выбора наименьшего---------------------


void __fastcall TForm1::search(int k,int *index)
{
int i,c;          //c=левая переменная
unsigned Wait=0;  //конкретное ожидание
int ax[KolReisMax];  //временный массив
if(k==1)          //k - кол-во перестановок
 {
        for (i=0;i<KolReis;i++)Wait+=TW[i][index[i]]; // подсчет времени ожид
        if (WaitMin>Wait)                     //выбор меньшего
                {
                WaitMin=Wait;
                for (i=0;i<KolReis;i++)IndOptim[i]=index[i];
                }
        Wait=0;
 return;
 }
for (i=0;i<KolReis;i++) ax[i]=index[i];
search(k-1,ax);                              //search - рекурсивная функция
for(i=0;i<k-1;i++)
 {
  c=ax[i];ax[i]=ax[k-1];ax[k-1]=c;
  search(k-1,ax);
 }
}

//---------------------------------------------------------------------------
void __fastcall TForm1::ExitClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::LoadClick(TObject *Sender)
{
 EditKol->Text=5;
 float OtM[5]={6,7.5,11.5,19.00,24.5};
 float OtA[5]={5.5,9.00,15.00,18.5,24};
 for (int i=0;i<5;i++)
 {
  GridMA->Cells[i][1]=OtM[i];
  GridAM->Cells[i][1]=OtA[i];
 }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ResetClick(TObject *Sender)
{
FormCreate(NULL);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::clear()
{
 for(int i=0;i<KolReisMax;i++)
 {
 if (i+1!=KolReisMax) { GridRez->Cells[0][i+1]=" ";
                        GridRez->Cells[1][i+1]=" "; }
 for(int j=0;j<KolReisMax;j++)
 GridTW->Cells[i][j]=" ";
 }
}

//-------------------------------------------------------------
void __fastcall TForm1::error()

{
                MessageBox(Handle,
                "Введено некорректное расписание ",
                " Недоступная операция",
                MB_OK | MB_ICONERROR);
}
//--------------------------------------------------------------