N queens, X на Y питання про інтерв'ю з рішенням ради


10

Мене сьогодні в інтерв'ю мені задали наступне питання, і я про це думав з тих пір. Я не зміг відповісти на це і не зміг знайти рішення в Інтернеті.

Давши шахову дошку розмірами X на Y і N королеви, визначте, чи можна розташувати ці королеви на дошці так, щоб вони не могли атакувати один одного.

Плата 2 х 3 з двома королевами має рішення, щоб алгоритм повернув істину:

Q . .
. . Q

Я шукаю підхід до програмування цієї головоломки, а не просто способи її розв'язання, наприклад, на папері.


Найкращий перший пошук , безумовно, варіант, як і інші евристики пошуку
Джейсон

2
номінований на одне з найгірших запитань про інтерв'ю - якщо програмне забезпечення, над яким вони працюють, не покладається на зворотні рішення, і в цьому випадку це абсолютно актуально
Стівен А. Лоу

1
Чесно кажучи, інтерв'юер сказав, що це просто зайвий вид кредиту. Решта інтерв'ю була досить законним IMO. Мені було просто цікаво.
співбесідник

Можливо, це був тест, якщо він зробив би симуляцію з зворотним відстеженням або (подумав про пошук) рішення O (1), використовуючи факти, викладені Калебом у своїй відповіді. Здатність програмувати прості речі - це не все, що потрібно в роботі.
Сопель

Завдання домашнього завдання явно не виходять за рамки.
jwenting

Відповіді:


16

Це не дуже важлива проблема з точки зору програмування. Ви можете створити рекурсивний алгоритм, який намагається здійснити кожну композицію, приблизно так:

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)
}

Якщо ви трохи подумаєте про проблему, то зрозумієте, що немає способу помістити N королеви на дошці, де X <N або Y <N, тому що це вимагатиме, щоб принаймні дві королеви опинилися в одному ранзі або файлі, і тому вони б атакували один одного. Якщо ви прочитаєте про проблему n-queens, швидко дізнаєтесь, що завжди можна розмістити N queens на дошці NxN для N> 3. Тепер ми знаємо, що відповідь "НЕ" (X <N або Y <N) і ТАК для (X> = N і Y> = N, N> 3). Залишилися лише спеціальні випадки:

  • N = 1 (ТАК)
  • N = 2 (ТАК для X> = 2 і Y> 2 або навпаки)
  • N = 3 (ТАК для X> = 3 і Y> 3 або навпаки)

Тепер наша приємна рекурсивна функція стає простою функцією, яка просто порівнює N до X і Y і повертає консервований результат. Це чудово з точки зору продуктивності, оскільки відповідь ви можете отримувати постійно. З точки зору програмування, це не так здорово, тому що ви усвідомлюєте, що на даний момент питання стосується насправді питання про те, наскільки добре ви можете розгадувати загадки, ніж про вашу здатність писати рекурсивну функцію.

(І хлопче о хлопчику, я дуже сподіваюся, що я не зробила жодної тупої помилки у відповіді на свої розумні штани. ;-)


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.Насправді я думаю, що інтерв'юер чекав на це рішення O (1), оскільки це в кінцевому підсумку краще і не очевидно для багатьох людей. Проблема nxn queen в усіх курсах програмування є вправою для рекурсії - багато людей не задумаються глибше, побачивши цю проблему ще раз.
Сопель

4

Якщо інтерв'юер попросив вас написати код проблеми, то я вважаю, що це не справедливо. Алгоритм вимагає роботи. Однак, якщо ідея полягала в тому, щоб показати інтерв'юеру класи, методи чи якісь поняття, які вам потрібно буде використовувати, або щось подібне, то це може бути справедливим питанням.

Проблема є класичною проблемою інформатики і обговорюється в багатьох таких книгах. Чудове пояснення, з анімацією та 12 різними рішеннями разом з деяким кодом можна знайти тут:

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

Також код можна знайти тут: http://www.codeproject.com/KB/java/EightQueen.aspx

Не відчувайте себе погано з цього приводу, як я вже сказав, це нелегко.


0

Це справді коментар, але він не вміщується там ...

Шахова дошка має 8х8 квадратів, не більше і не менше (ці питання завжди дратують мене таким підходом спеціальної шахової дошки).

Але в будь-якому випадку, якщо у вас є шахівниця x * y, і n королеви, і якщо ви вважаєте, що королева «приймає» ці поля

введіть тут опис зображення

ви могли б просто створити двовимірний масив і "позначити" всі поля, на які атакує одна королева. Потім помістіть інше (з середини дошки), позначте інші поля тощо, поки не запустите жодне з полів або королеви.

Це, звичайно, дуже спрощений підхід, оскільки, якщо розміщуватися погано, я набираю, що максимальна кількість королеви може змінюватися.

Хм, щойно це знайшли - проблема 8 королеви.


Я запропонував цей точний алгоритм спочатку, але вважаю, що вам не гарантовано, що якщо ви скористаєтеся таким підходом, і в кінцевому підсумку не буде місця, де можна поставити останню королеву, що ви справді визначили, що це неможливо. Ви виключили лише цю угоду. Це в основному застосування евристики найближчого сусіда.
співбесідник

@Interviewee - Так, я знаю. Це якраз те, про що я думав з голови. Як було сказано, це цікава проблема, і, ймовірно, її можна вдосконалити, але в 4 ранку (тут) мені просто лінь думати. До речі, як пройшло інтерв'ю?
Грак

@Interviewee, це правильна ідея. Частини, якої не вистачає, полягає в тому, що якщо ви виявите, що для останньої королеви немає місця, ви створюєте резервні копії та спробуйте інше місце для другої до останньої королеви. Якщо для цієї королеви немає місця, яке дозволяє розміщувати останню королеву, ви резервуєте інший рівень та спробуйте інше місце для третьої до останньої королеви тощо.
Калеб

Мені подобається, що твій аватар є шаховим твором :)
warren

0

В основному алгоритм зворотного треку працює так:

  1. Створіть масив X by Y. Встановіть порожні всі квадрати.

  2. Встановіть кількість королеви в нуль.

  3. Встановіть поточну позицію (1,1)

  4. Подивіться, чи можете ви розмістити королеву в поточному положенні.

  5. Якщо ви можете, встановіть масив (X, Y) на королеву, збільште кількість королеви. Якщо ви розмістили всю королеву, зупиніться , у вас є рішення.

  6. Якщо поточне положення не (X, Y), посиліть поточне положення та перейдіть до кроку 4.

  7. Знайдіть королеву в останньому положенні (ту, яка є останньою в тому порядку, в якому ви збільшуєте посади). Встановіть поточну позицію на позицію цієї королеви, видаліть її та зменшіть кількість королеви.

  8. Якщо кількість королеви дорівнює нулю, зупиніться , рішення немає.

  9. Підвищення поточної позиції.

  10. Перейдіть до кроку 4.


У цьому описі алгоритм не відкликає правильно: він видаляє лише останню розміщену королеву; Ви ризикуєте ніколи не пробувати раніше королеви на інших посадах.
Каспер ван ден Берг

@KaspervandenBerg Алгоритм повертається правильно. Я відповів би безпосередньо на вашу критику, але я, чесно кажучи, не можу це зрозуміти. Я не знаю, що ви маєте на увазі під "останньою королевою, що розмістилася". Вона видалить останню розміщену королеву, але будь-яка королева може стати останньою розміщеною королевою після того, як королеви розміщені після її видалення. Це дозволить відступити, наскільки це потрібно, видаляючи королеви в зворотному порядку, в якому вони були розміщені.
Девід Шварц

0

Додавання до інших відповідей: створення двовимірного масиву лише ускладнює код.

Вам просто потрібен вектор розміром 8 для звичайної шахової дошки. Або 8 + 1, якщо на зразок C 1-ї позиції дорівнює 0, тільки для спрощення коду, і мати справу з 1-8, а не 0-7.

Якщо ви думаєте про те, що x - ваша позиція в масиві, а y - вміст позиції. наприклад дошка [1] = 8 означає, що перша королева знаходиться в [1,8].

Таким чином, вам потрібно лише перевірити перевірку стовпців.

Під час факультету я натрапив на дуже стару книгу (60-ті роки?) Про алгоритми, реалізовані в Dartmouth BASIC, які реалізували проблему 8 королеви, використовуючи менше можливості пам'яті (будучи такою старою, це має сенс).

Наскільки я пам’ятаю, він використовував ідею вектора, і це по суті грубо змусило всі позиції в дошці за допомогою двох циклів FOR. Для перевірки достовірності позиції він використовував третій цикл, цикл WHILE у кожній позиції, повертаючись у вектор, і перевіряючи рівне число або формулу, використовуючи дотичну операцію для перевірки діагоналей.

На жаль, я програв цю книгу ...

Згаданий алгоритм знайшов усі рішення для проблеми n-queen.


0

Якщо вам просто потрібно написати алгоритм, щоб визначити, чи існує така домовленість, то подивіться на існуюче дослідження:
Вісім головоломок королеви у Вікіпедії .

Ви можете тривіально повернути false, якщо N> min (X, Y).
Прочитавши цю сторінку, ви знаєте, що повернути істину, якщо N <= min (X, Y) і 2, 3! = Min (X, Y).

Який залишає 2, 3 == хв (X, Y) і N <= хв (X, Y).

Добре, якщо N <min (X, Y), пошук рішення тривіальний.
Якщо N == хв (X, Y), рішення є лише, якщо 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

Очевидно, що рішення немає, якщо N> min (X, Y). В іншому випадку ви можете легко показати, що рішення для N = X = Y = 2, N = X = Y = 3. не існує. Для всіх інших випадків, здається, існує рішення. Зростає, що кількість рішень зростає зі зростанням N.

Ви можете знайти рішення шляхом вичерпного пошуку з зворотним відстеженням. Поставте королеву в перший рядок, стовпець 1. Поставте королеву в другий ряд, у перший стовпець, до якого королева у рядку 1 не може дійти. Поставте королеву в другий ряд і т. Д. Якщо королеву не можна поставити в рядок k, ви виймете її і перемістіть королеву в рядок k-1 в наступному незайнятому положенні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.