chore(CPlusPlus): add n-queens backtracking algorithm (#812)

Co-authored-by: Arsenic <54987647+Arsenic-ATG@users.noreply.github.com>
pull/849/head^2
Devang-Shah-49 2022-09-29 03:44:20 +05:30 committed by GitHub
parent 478a8c80c0
commit b67f5e1786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 0 deletions

View File

@ -0,0 +1,81 @@
/* Code contributed by Devang Shah to MakeContributions/DSA GitHub repository
Below CPlusPlus code displays all possible solutions for a N-Queens problem.
Problem: Given a N x N chess board, arrange N queens in a way such that no two queens attack each other. Two queens are attacking each other if they are in same row, same column or diagonal
Input: N
Output: All solutions ( in grid format {Q - Queen, * - empty cell} ) of the N-queens problem
Time Complexity: O(N!)
*/
#include <iostream>
using namespace std;
int a[30];
int place(int pos)
{
int i;
for (i = 1; i < pos; i++)
{
if ((a[i] == a[pos]) || ((abs(a[i] - a[pos]) == abs(i - pos))))
return 0;
}
return 1;
}
void print_sol(int n)
{
int i, j;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= n; j++)
{
if (a[i] == j)
cout << "Q\t";
else
cout << "*\t";
}
cout << "\n";
}
}
void queen(int n)
{
int k = 1;
a[k] = 0;
int count = 0;
while (k != 0)
{
a[k] = a[k] + 1;
while ((a[k] <= n) && !place(k))
a[k]++;
if (a[k] <= n)
{
if (k == n)
{
count++;
cout << "Solution #" << count << "\n";
print_sol(n);
}
else
{
k++;
a[k] = 0;
}
}
else
k--;
}
cout << "\nTotal solutions=" << count;
}
int main()
{
unsigned int n;
cin >> n;
if (n < 15)
queen(n);
else
cout << "Invalid input. Program crashed";
return 0;
}

View File

@ -203,3 +203,6 @@
- [Decimal To Octal](Number-system/decimal_to_octal.cpp)
- [Octal To Decimal](Number-system/octal_to_decimal.cpp)
## Backtracking
- [N-Queens Problem](Backtracking/n-queens.cpp)

View File

@ -0,0 +1,37 @@
# N-Queens Problem
N-Queens is a backtracking problem. Given a N x N chess board, our task is to arrange N queens in a way such that no two queens attack each other. Two queens are attacking each other if they are in same row, same column or diagonal. Minimum chess board size should be 4x4.
## Steps
1. Each row contains 1 queen
2. For each row, keep track of the valid columns for queen placement. # (NOTE in a clever way)
3. DFS, start from the first row, try each valid column and backtrack if necessary.
4. Note that we can encode left/right diagonals as indexes in the following way:
For any (r, c),
- its top-left to the bottom-right diagonal index is r c, ∈ (-n, n)
- its bottom-left to the top-right diagonal index is r + c, ∈ [0, 2n)
5. Each (r, c) takes the r-th row, c-th column, and the two diagonal indexes encoded above.
6. Now we can use 4 sets to indicate whether those row/col/diagonal have been taken, if yes, a queen cannot be placed at (r, c).
7. Moreover, if we search via dfs, proceeding row by row, we can avoid keeping # the row set, getting away with 3 sets only (column, and 2 diagonals).
8. Each set indicates whether the column/diagonal with the specified index has been taken.
## Example
Given size of Chessboard: **N=4**
2 solutions exists. They are:
![4-Queens solution image](https://tse3.mm.bing.net/th?id=OIP.9CG0udqpuL95M7-dksk1ZwHaDc&pid=Api&P=0)
## Time Complexity
O(N!)
## Implementation
- [C++](../../../algorithms/CPlusPlus/Backtracking/n-queens.cpp)
## Video URL
[Youtube Video explaining N-queens problem](https://youtu.be/xFv_Hl4B83A)