N queens, domanda di intervista con problemi decisionali X a Y

10

Mi è stata posta la seguente domanda in un'intervista di oggi e ci ho pensato da allora. Non ero in grado di rispondere e non sono stato in grado di trovare una soluzione online.

Dato una scacchiera con le dimensioni X di Y e N queens, determina se è possibile disporre queste regine sulla scacchiera in modo che non possano attaccarsi a vicenda.

Una scheda 2 x 3 con 2 regine ha una soluzione in modo che l'algoritmo restituisca true:

Q . .
. . Q

Sto cercando un approccio di programmazione per questo puzzle, non solo i modi per risolverlo su carta, per esempio.

    
posta Interviewee 15.09.2011 - 03:26
fonte

7 risposte

16

Questo non è (IMO) un problema molto interessante da un punto di vista della programmazione. Potresti trovare un algoritmo ricorsivo che provi ogni arrangiamento, qualcosa del genere:

bool try_queens(Board board, int n)
{
    if (n == 0) {
        // no queens left to place, so we're done
        return true
    }
    // try each open position until we find one that works
    for each position on the board {
        if (is_empty(board, position) and not is_attacked(board, position)) {
            place_queen(board, position)
            if (try_queens(board, n-1)) {
                return true
            }
            remove_queen(board, position)
        }
    }
    // if we get this far, there's no available position
    return false
}

main()
{
    initialize board(X,Y)
    return try_queens(board, N)
}

Se pensi un po 'al problema, ti renderai conto che non c'è modo di adattare N queens su una board dove X < N o Y < N perché ciò richiederebbe che almeno due regine finissero nello stesso grado o file, e quindi si attaccerebbero l'un l'altro. Se leggi il problema di n-queens, imparerai presto che è sempre possibile posizionare N queens su una scheda NxN per N > 3. Ora sappiamo che la risposta è NO per (X < N o Y < N) e YES per (X > = N e Y > = N, N > 3). Tutto ciò che rimane sono i casi speciali:

  • N = 1 (YES)
  • N = 2 (YES per X > = 2 e Y > 2 o viceversa)
  • N = 3 (YES per X > = 3 e Y > 3 o viceversa)

Quindi ora la nostra bella funzione ricorsiva diventa una semplice funzione che confronta solo N a X e Y e restituisce un risultato in scatola. È fantastico dal punto di vista delle prestazioni, dal momento che è possibile ottenere una risposta in tempo costante. Non è così bello da un punto di vista della programmazione perché ti rendi conto, a questo punto, che la domanda è più che altro su quanto riesci a risolvere i puzzle piuttosto che sulla tua capacità di scrivere una funzione ricorsiva.

(E ragazzo oh ragazzo, spero davvero che non abbia fatto un errore stupido nella mia risposta da smarty-pants. ;-))

    
risposta data 15.09.2011 - 05:35
fonte
4

Se l'intervistatore ti ha chiesto di scrivere il codice per il problema, allora penso che non sia giusto. L'algoritmo richiede lavoro. Tuttavia, se l'idea fosse di mostrare all'intervistatore le classi, i metodi o alcuni concetti che avresti bisogno di usare o qualcosa di simile, allora potrebbe essere una domanda giusta.

Il problema è un classico problema di informatica e viene discusso in molti di questi libri. Una spiegazione eccellente, con animazione e 12 diverse soluzioni insieme a qualche codice potrebbe essere trovata qui:

link

Anche il codice può essere trovato qui: link

Non mi sento male per questo, come ho detto, non è facile.

    
risposta data 15.09.2011 - 05:36
fonte
0

Questo è più di un commento, ma non si adatta a questo ...

Una scacchiera ha 8x8 quadrati, né più né meno (queste domande mi infastidiscono sempre con quell'approccio di una scacchiera personalizzata).

Ma comunque, se hai una scacchiera x * ye n regine e prendi che la regina "prende" questi campi

potrestisemplicementecreareunamatricebidimensionalee"contrassegnare" tutti i campi che una regina attacca. Quindi posiziona l'altro (dalla parte centrale della scheda), contrassegna i campi rimanenti e così via ... finché non esegui uno dei campi o delle regine.

Questo è ovviamente un approccio molto semplificato, dal momento che se posizionato male, ritengo che il numero massimo di regine varierebbe.

Hmm, hai appena trovato anche questo - 8 problemi con le regine.

    
risposta data 15.09.2011 - 03:37
fonte
0

Fondamentalmente, l'algoritmo di backtrack funziona così:

  1. Crea un array X by Y. Imposta tutti i quadrati da svuotare.

  2. Imposta il conteggio delle coppie su zero.

  3. Imposta la tua posizione corrente su (1,1)

  4. Verifica se puoi posizionare una regina nella posizione corrente.

  5. Se puoi, imposta Array (X, Y) su queen, incrementa il numero di re. Se hai inserito tutte le donne, stop , hai una soluzione.

  6. Se la posizione corrente non è (X, Y), incrementa la posizione corrente e vai al punto 4.

  7. Trova la regina nell'ultima posizione (quella che viene per ultima nell'ordine in cui incrementi le posizioni). Imposta la posizione corrente sulla posizione di quella regina, rimuovila e decrementa il conteggio delle donne.

  8. Se il conteggio delle coppie è pari a zero, stop , non c'è soluzione.

  9. Incrementa la posizione corrente.

  10. Vai al passaggio 4.

risposta data 15.09.2011 - 12:53
fonte
0

Aggiungendo alle altre risposte: la creazione di un array bidimensionale complica il codice.

Hai solo bisogno di un vettore di dimensione 8 per una scacchiera normale. O 8 + 1 se come C 1a posizione è 0, solo per semplificare il codice e trattare con 1-8 e non 0-7.

Se pensi che x sia la tua posizione nell'array e che sia il contenuto della posizione. per esempio board [1] = 8 significa che la prima regina è a [1,8].

In questo modo, devi solo verificare la convalida delle colonne.

All'epoca dei docenti, mi sono imbattuto in un libro molto vecchio (anni '60?), sugli algoritmi implementati in Dartmouth BASIC, che implementava il problema dell'8 regina usando meno memoria possibile (essendo così vecchio, ha senso).

Per quanto mi ricordo, ha usato l'idea del vettore, e in pratica ha brutalmente forzato tutte le posizioni nella scacchiera con due cicli FOR. Per verificare la validità della posizione, ha utilizzato un terzo ciclo, un ciclo WHILE in ogni posizione torna nel vettore e controlla un numero uguale o una formula utilizzando un'operazione tangente per verificare le diagonali.

Purtroppo ho perso conoscenza di quel libro ...

Tale algoritmo ha trovato tutte le soluzioni per il problema della n-regina.

    
risposta data 03.09.2017 - 10:09
fonte
0

Se devi solo scrivere un algoritmo per determinare se esiste una tale disposizione, allora guarda la ricerca esistente:
Otto puzzle delle regine su Wikipedia .

Puoi banalmente restituire false se N > min (X, Y).
Dopo aver letto quella pagina, sai di restituire true se N < = min (X, Y) e 2, 3! = Min (X, Y).

Che lascia 2, 3 == min (X, Y) e N < = min (X, Y).

Bene, se N < min (X, Y), trovare una soluzione è banale.
Se N == min (X, Y), c'è solo una soluzione se max (X, Y) > N.

f(X, Y, N)
    if X < Y => f(Y, X, N)
    if Y > N => false
    => (Y < N) or (Y != 2 and Y != 3) or (X > N)
    
risposta data 03.09.2017 - 13:26
fonte
0

Ovviamente non esiste una soluzione se N > min (X, Y). Altrimenti, puoi facilmente dimostrare che non c'è soluzione per N = X = Y = 2, N = X = Y = 3. Per tutti gli altri casi sembra esserci una soluzione. Il numero di soluzioni sembra aumentare man mano che N cresce.

Puoi trovare una soluzione attraverso la ricerca esauriente con il backtracking: Metti una regina nella prima fila, colonna 1. Metti una regina nella seconda fila, nella prima colonna che la regina nella riga 1 non può raggiungere. Metti una regina nella seconda fila, ecc. Se una regina non può essere messa nella riga k, allora la rimuovi e muovi la regina nella riga k-1 nella posizione successiva non occupata.

    
risposta data 03.09.2017 - 15:27
fonte

Leggi altre domande sui tag