Álvaro González Sotillo

Algunas reinas

Me han retado a hacer un programa que resuelva el problema de las n-reinas. Esta es mi solución en c++ básico: sin class / struct , sin memoria dinámica y sin punteros a función. Solo utilizo assert , printf y system para conseguir la hora de inicio y fin del programa.

El límite práctico parece estar en las 30 reinas, con alrededor de 12 segundos de cálculo.

1. Algunas reinas

#include <stdio.h>
#include <stdlib.h>
#include <cassert>

using namespace std;



const int maxSize = 100;
const int notSeized = maxSize+1;

int seizedAtLevel[maxSize][maxSize];

void initSeized(){
  for( int col = 0 ; col < maxSize ; col += 1 ){
    for( int row = 0 ; row < maxSize ; row += 1 ){
      seizedAtLevel[col][row] = notSeized;
    }
  }
}

bool seized(const int col, const int row, const int currentLevel ){
  return seizedAtLevel[col][row] <= currentLevel;
}

void setSeizedValue(const int col, const int row, const int currentLevel, const int value ){

  if( col < 0 || row < 0 || col >= maxSize || row >= maxSize ){
    // out of board
    return;
  }
  
  if( seizedAtLevel[col][row] < currentLevel ){
    // already seized by previous queen
    return;
  }
  seizedAtLevel[col][row] = value;
}


void changeSeizedCells(const int row, const int level, const int size, const int value ){
  for( int d = 1 ; d < size-level ; d += 1 ){
    // same row
    setSeizedValue(level+d,row,level,value);

    // upwards diagonal
    setSeizedValue(level+d,row-d,level,value);

    // downwards diagonal
    setSeizedValue(level+d,row+d,level,value);
  }
}


void dumpSeized(const int size){
  for( int row = 0 ; row < size ; row += 1 ){
    for( int col = 0 ; col < size ; col += 1 ){
      printf( "\t%d", seizedAtLevel[col][row] );
    }
    printf( "\n");
  }
}

bool stillPossible( const int level, const int size ){
  for( int col = level+1 ; col < size ; col += 1 ){
    int freeCells = 0;
    for( int row = 0; row < size ; row += 1 ){
      if( !seized(col,row,level) ){
        freeCells += 1;
      }
    }
    if( freeCells < col-level-1){
      // there are no enough free cells in the column
      return false;
    }
  }
  return true;
}

bool placeQueenAtLevel( const int level, const int size, int queensRows[] ){
  assert(size < maxSize );

  // printf( "\n INTENTANDO NIVEL:%d\n", level);
  // dumpSeized(size);
  
  if( level == size ){
    return true;
  }
  
  for( int row = 0 ; row < size ; row += 1 ){

    if( seized(level,row,level) ){
      continue;
    }

    // place queen in col=level, row=row
    queensRows[level] = row;
    changeSeizedCells(row,level, size,level);

    // try next queen
    if( stillPossible(level,size) ){
      if( placeQueenAtLevel(level+1,size,queensRows) ){
        return true;
      }
    }

    // remove queen from col=level, row=row
    changeSeizedCells(row,level, size,notSeized);
  }

  return false;
}

void dumpQueens(int queensRows[], int size){
  for( int row = 0 ; row < size ; row += 1 ){
    for( int col = 0 ; col < size ; col += 1 ){
      const char cell = (col+row)%2==0 ? '.' : ' ';
      printf( " %c", queensRows[col]==row ? 'Q' : cell );
    }
    printf( "\n");
  }

}
  
int main( int argc, char *argv[] ){

  system("date");

  int currentQueen = 0;
  const int size = 31;

  int queensRows[size];

  initSeized();
  bool result = placeQueenAtLevel(0,size,queensRows);

  printf( "Conseguido:%s\n", result ? "Si" : "No");
  if( result ){
    dumpQueens(queensRows, size);
  }

  system("date");
  
}
mié 21 oct 2020 10:58:18 CEST
mié 21 oct 2020 10:58:34 CEST
Conseguido:Si
 Q   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   .   .   .   .   . Q .   .   .   .   .   .   .  
 . Q .   .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   .   .   .   .   .   .   .   . Q .   .   .   .  
 .   Q   .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   .   .   .   .   .   .   Q   .   .   .   .   .  
 .   .   .   .   .   .   .   .   .   .   .   .   Q   .   .   .
   .   .   .   .   .   .   .   .   .   . Q .   .   .   .   .  
 .   . Q .   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   .   .   . Q .   .   .   .   .   .   .   .   .  
 .   .   Q   .   .   .   .   .   .   .   .   .   .   .   .   .
   .   .   .   Q   .   .   .   .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   .   .   .   .   .   . Q .   .   .   .
   .   .   . Q .   .   .   .   .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   .   . Q .   .   .   .   .   .   .   .
   .   .   Q   .   .   .   .   .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   .   .   .   Q   .   .   .   .   .   .
   .   .   .   .   Q   .   .   .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   .   .   .   .   .   .   .   .   Q   .
   .   .   .   .   .   .   .   .   .   .   .   .   Q   .   .  
 .   .   .   .   .   .   .   .   .   .   .   .   .   .   . Q .
   .   .   .   .   .   .   .   .   .   .   .   .   . Q .   .  
 .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   Q
   .   .   .   .   .   .   .   .   .   .   .   .   .   Q   .  
 .   .   .   .   .   .   .   .   .   .   . Q .   .   .   .   .
   .   .   .   .   .   .   . Q .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   .   .   . Q .   .   .   .   .   .   .
   .   .   .   .   . Q .   .   .   .   .   .   .   .   .   .  
 .   .   .   .   .   .   . Q .   .   .   .   .   .   .   .   .
   .   .   .   .   .   Q   .   .   .   .   .   .   .   .   .  
 .   .   .   .   Q   .   .   .   .   .   .   .   .   .   .   .