N rainhas, X por Y placa decisão problema entrevista entrevista


10

Foi-me feita a seguinte pergunta em uma entrevista hoje e penso nisso desde então. Não consegui responder e não consegui encontrar uma solução online.

Dado um tabuleiro de xadrez com as dimensões X das rainhas Y e N, determine se é possível organizar essas rainhas no tabuleiro de modo que não possam atacar umas às outras.

Uma placa 2 x 3 com 2 rainhas tem uma solução para que o algoritmo retorne verdadeiro:

Q . .
. . Q

Estou procurando uma abordagem de programação para esse quebra-cabeça, não apenas maneiras de resolvê-lo no papel, por exemplo.


Best First Search é certamente uma opção, assim como outras heurísticas de pesquisa
Jason

2
nomeado para uma das piores perguntas da entrevista de sempre - a menos que o software que eles trabalham em depende de soluções backtracking, caso em que é totalmente relevante
Steven A. Lowe

11
Para ser justo, o entrevistador disse que isso era simplesmente um tipo de crédito extra. O resto da entrevista foi bastante legal. Eu só estava curioso.
Entrevistado

Talvez fosse um teste se ele faria uma simulação com retorno ou (pense em encontrar) solução O (1) usando os fatos declarados por Caleb em sua resposta. A capacidade de programar coisas simples não é tudo o que se precisa no trabalho.
Sopel

as tarefas de casa estão explicitamente fora do escopo aqui.
jwenting 12/09

Respostas:


16

Este não é (IMO) um problema muito interessante do ponto de vista da programação. Você pode criar um algoritmo recursivo que tente todos os arranjos, algo como isto:

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 você pensar um pouco sobre o problema, perceberá que não há como encaixar N rainhas em um quadro em que X <N ou Y <N, porque isso exigiria que pelo menos duas rainhas terminassem na mesma fila ou arquivo, e eles atacariam um ao outro. Se você ler sobre o problema das n-rainhas, aprenderá rapidamente que sempre é possível colocar N rainhas em uma placa NxN para N> 3. Agora sabemos que a resposta é NÃO para (X <N ou Y <N) e SIM para (X> = N e Y> = N, N> 3). Tudo o que resta são os casos especiais:

  • N = 1 (SIM)
  • N = 2 (SIM para X> = 2 e Y> 2 ou vice-versa)
  • N = 3 (SIM para X> = 3 e Y> 3 ou vice-versa)

Portanto, agora nossa agradável função recursiva se torna uma função simples que apenas compara N a X e Y e retorna um resultado fixo. Isso é ótimo do ponto de vista do desempenho, pois você pode obter uma resposta em tempo constante. Não é tão bom do ponto de vista de programação, porque você percebe, neste momento, que a pergunta é realmente mais sobre o quão bem você pode resolver quebra-cabeças do que sobre sua capacidade de escrever uma função recursiva.

(E garoto, oh garoto, eu realmente espero que não tenha cometido algum erro estúpido na minha resposta. ;-)


That's great from a performance point of view, since you can get an answer in constant time. It's not so great from a programming point of view because you realize, at this point, that the question is really more about how well you can solve puzzles than it is about your ability to write a recursive function.Na verdade, acho que o entrevistador estava esperando por essa solução O (1) porque, em última análise, é melhor e não é óbvia para muitas pessoas. O problema do nxn queen está em todos os cursos de programação como um exercício de recursão - muitas pessoas não pensam mais profundamente ao ver esse problema novamente.
Sopel

4

Se o entrevistador pediu para você escrever o código do problema, acho que não é justo. O algoritmo requer trabalho. No entanto, se a ideia era mostrar ao entrevistador as classes, métodos ou alguns conceitos que você precisaria usar ou algo semelhante, então pode ser uma pergunta justa.

O problema é um problema clássico de Ciência da Computação e é discutido em muitos desses livros. Uma excelente explicação, com animação e 12 soluções diferentes, juntamente com algum código, pode ser encontrada aqui:

http://en.wikipedia.org/wiki/Eight_queens_puzzle

Também código pode ser encontrado aqui: http://www.codeproject.com/KB/java/EightQueen.aspx

Não se sinta mal com isso, como eu disse, não é fácil.


0

Isso é realmente mais um comentário, mas não se encaixa lá ...

Um tabuleiro de xadrez tem quadrados 8x8, nem mais nem menos (essas perguntas sempre me incomodam com a abordagem de um tabuleiro de xadrez personalizado).

Mas de qualquer maneira, se você tem um tabuleiro de xadrez x * y, n rainhas e considera que a rainha "pega" esses campos

insira a descrição da imagem aqui

você pode apenas criar uma matriz bidimensional e "sinalizar" todos os campos que uma rainha ataca. Em seguida, coloque o outro (do meio do quadro), sinalize os campos restantes e assim por diante ... até executar campos ou rainhas.

Essa é, obviamente, uma abordagem muito simplificada, pois, se posicionada de maneira incorreta, eu acho que o número máximo de rainhas varia.

Hmm, acabei de encontrar isso também - problema de 8 rainhas.


Eu propus esse algoritmo exato no começo, mas considero que você não tem garantia de que, se você seguir essa abordagem e acabar sem lugares para colocar sua última rainha, realmente determinou que é impossível. Você apenas eliminou esse arranjo específico. Isso é basicamente uma aplicação da heurística do vizinho mais próximo.
Entrevistado

@ Entrevistador - Sim, eu sei. Isso é apenas algo que eu pensei em cima da minha cabeça. Como foi dito, é um problema interessante e provavelmente poderia ser melhorado, mas às 4 da manhã (aqui) estou com preguiça de pensar. Btw, como foi a entrevista?
Rook

@ Entrevistador, esta é a ideia certa. A parte que falta é que, se você descobrir que não há lugar para a última rainha, faça um backup e tente uma posição diferente para a penúltima rainha. Se não houver lugar para essa rainha que permita a colocação da última rainha, você fará o backup de outro nível e tentará um local diferente para a terceira e última rainha, e assim por diante.
Calebe

Eu gosto que o seu avatar é uma peça de xadrez :)
Warren

0

Basicamente, o algoritmo de retorno funciona assim:

  1. Crie uma matriz X por Y. Defina todos os quadrados para esvaziar.

  2. Defina a contagem da rainha como zero.

  3. Defina sua posição atual para (1,1)

  4. Veja se você pode colocar uma rainha na posição atual.

  5. Se puder, defina Matriz (X, Y) como rainha, aumente a contagem de damas. Se você colocou toda a rainha, pare , você tem uma solução.

  6. Se a posição atual não for (X, Y), aumente a posição atual e vá para a etapa 4.

  7. Encontre a rainha na última posição (a que vier por último na ordem em que você aumenta as posições). Defina a posição atual para a posição da rainha, remova-a e diminua a contagem de damas.

  8. Se a contagem de damas for zero, pare , não há solução.

  9. Incremente a posição atual.

  10. Vá para o passo 4.


Nesta descrição, o algoritmo não retrocede corretamente: ele remove apenas a última rainha posicionável; corre o risco de nunca tentar rainhas anteriores em outras posições.
Kasper van den Berg,

@KaspervandenBerg O algoritmo retorna novamente corretamente. Eu responderia diretamente às suas críticas, mas sinceramente não consigo entender. Não sei o que você quer dizer com "última rainha que pode ser colocada". Ele removerá apenas a última rainha colocada, mas qualquer rainha poderá se tornar a última rainha depois que as rainhas forem colocadas após a remoção. Ele voltará na medida do necessário, removendo as rainhas no reverso da ordem em que foram colocadas.
David Schwartz

0

Adicionando às outras respostas: a criação de uma matriz bidimensional apenas complica o código.

Você só precisa de um vetor do tamanho 8 para um tabuleiro de xadrez comum. Ou 8 + 1 se C 1ª posição for 0, apenas para simplificar o código, e lidar com 1-8 e não 0-7.

Se você pensa em x ser sua posição na matriz e y ser o conteúdo da posição. por exemplo, bordo [1] = 8 significa que a primeira rainha está em [1,8].

Dessa forma, você só precisa verificar a validação das colunas.

No momento da faculdade, me deparei com um livro muito antigo (anos 60?), Sobre algoritmos implementados no Dartmouth BASIC, que implementava o problema das 8 rainhas usando menos memória possível (sendo tão antiga, faz sentido).

Tanto quanto me lembro, ele usou a idéia de vetor e essencialmente bruta forçou todas as posições no quadro com dois ciclos FOR. Para verificar a validade da posição, ele usou um terceiro loop, um ciclo WHILE em cada posição volta no vetor e verifica um número igual ou uma fórmula usando uma operação tangente para verificar as diagonais.

Infelizmente, eu perdi a noção desse livro ...

O referido algoritmo encontrou todas as soluções para o problema n-queen.


0

Se você apenas tiver que escrever um algoritmo para determinar se esse arranjo existe, observe a pesquisa existente:
Oito rainhas do enigma na Wikipedia .

Você pode retornar trivialmente false se N> min (X, Y).
Depois de ler essa página, você retornará true se N <= min (X, Y) e 2, 3! = Min (X, Y).

O que deixa 2, 3 == min (X, Y) e N <= min (X, Y).

Bem, se N <min (X, Y), encontrar uma solução é trivial.
Se N == min (X, Y), existe apenas uma solução 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)

0

Obviamente, não há solução se N> min (X, Y). Caso contrário, você pode mostrar facilmente que não há solução para N = X = Y = 2, N = X = Y = 3. Para todos os outros casos, parece haver uma solução. O número de soluções parece aumentar à medida que N cresce.

Você pode encontrar uma solução através de pesquisa exaustiva com retorno: Coloque uma dama na primeira linha, coluna 1. Coloque uma dama na segunda linha, na primeira coluna que a rainha da linha 1 não pode alcançar. Coloque uma dama na segunda fila, etc. Se uma dama não puder ser colocada na fila k, remova-a e mova a dama na fila k-1 na próxima posição desocupada.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.