Backtracking : Les cavaliers

Le problème des cavaliers consiste à déplacer un cavalier sur un échiquier pour qu'il parcourt l'intégralité des cases, sans passer deux fois au même endroit. Il existe de nombreuses solutions à ce problème : Wikipedia indique 26 534 728 821 064 possibilités. Ce programme est capable de les calculer, mais en raison du nombre colossal de possibilités, le processus est extrêmement long.

// pb du cavalier

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>

#define DIM 8
int dx[]={1, 1, 2, 2, -1, -1, -2, -2};
int dy[]={2, -2, 1, -1, 2, -2, 1, -1};
FILE *fichier;

typedef struct {
  int maxcase;
  int nombreCasesExplorees;
  int libre[DIM][DIM];
  int chemin_x[DIM*DIM];
  int chemin_y[DIM*DIM];
} Situation;

void afficher (Situation *sit)
{
int i;
static n=0;

  fprintf (fichier,"\n----%d\n",n++);
  for (i= 0 ; i< DIM*DIM; i++)
    fprintf (fichier,"%d-%d\n",sit->chemin_x[i],sit->chemin_y[i]);
  printf ("%d\n",n);
}

inline int case_ok (Situation *sit, int x, int y)
{

  return (x>0) && (x<9) && (y<9) && (y>0) && sit->libre[x-1][y-1];
}

inline void deplace (Situation *sit, int x, int y)
{

  sit->libre[x-1][y-1] = 0;
  sit->chemin_x[sit->nombreCasesExplorees] = x;
  sit->chemin_y[sit->nombreCasesExplorees++] = y;
  if (sit->nombreCasesExplorees > sit->maxcase) {
    sit->maxcase = sit->nombreCasesExplorees;
    printf ("\a");
  }
}

inline void revient (Situation *sit)
{
  sit->nombreCasesExplorees--;
  sit->libre[sit->chemin_x[sit->nombreCasesExplorees]-1]
        [sit->chemin_y[sit->nombreCasesExplorees]-1] = 1;
  sit->chemin_x[sit->nombreCasesExplorees]=0;
  sit->chemin_y[sit->nombreCasesExplorees]=0;

}




void Cavalier (Situation *sit)
{
int x,y,xs,ys,i;

  gotoxy (1,1);
  printf ("%2.2d",sit->maxcase);
  if (sit->nombreCasesExplorees == DIM*DIM)
    afficher (sit);
  else
  {
    x = sit->chemin_x[sit->nombreCasesExplorees -1];
    y = sit->chemin_y[sit->nombreCasesExplorees -1];
    for (i=0; i<8; i++) {
      xs = x + dx[i];
      ys = y + dy[i];
      if (case_ok (sit, xs, ys)) {
        deplace (sit, xs, ys);
        Cavalier (sit);
        revient (sit);
      }
    }
  }
}

void Init (Situation *sit,int x, int y)
{
int i;
int j;

  for (i=0; i<DIM; i++)
    for (j=0; j<DIM; j++) {
      sit->libre [i][j] = 1;
      sit->chemin_x[i+j*DIM] = 0;
      sit->chemin_y[i+j*DIM] = 0;
    }
  sit->maxcase = 0;
  sit->nombreCasesExplorees = 1;
  sit->libre[x-1][y-1] = 0;
  sit->chemin_x[0] = x;
  sit->chemin_y[0]= y;
}



main ()
{
Situation situation;
int xinit,yinit;
time_t t1,t2;


  clrscr ();
  fichier = fopen ("cavalier.out", "a");
  if (fichier == NULL) {
    printf ("Erreur d'ouverture du fichier\n");
    exit (1);
  }     
  for (xinit=4; xinit > 0; xinit--)
    for (yinit=1; yinit <= xinit; yinit++) {
      Init (&situation, xinit, yinit);
      t1 = time(NULL);
      Cavalier (&situation);
      t2 = time(NULL);
      printf ("temps = %f", difftime(t2,t1));
  }
  fclose (fichier);
  return 0;
}

Une solution

Echiquier avec les positions successives
42 51 40 37 44 49 56 35
61 38 43 50 55 36 45 48
52 41 60 39 30 47 34 57
1 62 29 54 59 32 23 46
28 53 2 31 22 25 58 33
63 8 17 26 3 12 21 24
16 27 6 9 14 19 4 11
7 64 15 18 5 10 13 20