Stuck in an infinite loop (Knight's Tour Problem) - c++

The Knight's Tour Problem:
The knight is placed on the first block of an empty board and, moving according to the rules of chess, must visit each square exactly once. Print the path such that it covers all the blocks.
Could not understand why the code is stuck in an infinite loop. wasted hours still no clue.
I have the solution but couldn't understand why this particular code is not working.
#include<bits/stdc++.h>
using namespace std;
#define N 8
//possible moves
int rowMove[] = {2,1,-1,-2,-2,-1,1,2};
int colMove[] = {1,2,2,1,-1,-2,-2,-1};
void printBoard(vector<vector<int>> visited)
{
for(int i=0; i<N; i++)
{
for(int j=0;j<N;j++)
cout<<visited[i][j]<<" ";
cout<<endl;
}
cout<<endl;
}
//check if the given move is valid
bool isValid(vector<vector<int>> visited,int row, int col)
{
return (row>=0 && row<N && col>=0 && col<N && visited[row][col]==0);
}
bool solveKnight(vector<vector<int>> visited,int row, int col,int move)
{
//printBoard(visited);
if(move==N*N)
{
printBoard(visited);
return true;
}
else
{
for(int i=0;i<8;i++)
{
int newRow = row + rowMove[i];
int newCol = col + colMove[i];
if(isValid(visited,newRow,newCol))
{
move++;
visited[newRow][newCol] = move;
if(solveKnight(visited,newRow,newCol,move))
return true;
move--;
visited[newRow][newCol]=0;
}
}
}
return false;
}
int main()
{
vector<vector<int>> visited(N,vector<int>(N,0));
visited[0][0]=1;
if(!solveKnight(visited,0,0,1))
cout<<"not possible";
return 0;
}

There are two things wrong here:
You're copying over the 64-int vector every. single. time.
You're printing 9 lines to stdout every. single. time.
Both of these are extremely expensive operations. And you could recurse up to 8^64 = 2^192 times. That's not an insignificant number.
If you pass your vector by reference and kill the printBoard at the beginning of every recursive call...viola! https://ideone.com/K0DU3q

Related

Why my C++14 KosaRaju algo getting TLE when a similar written code runs much faster

TLE code completes at 2.1 secs. I'm also passing many things through reference but it's still throwing a TLE. Why this code takes so much time?
here is the problem at hackerearth:
https://www.hackerearth.com/problem/algorithm/falling-dominos-49b1ed46/
Dominos are lots of fun. Children like to stand the tiles on their side in long lines. When one domino falls, it knocks down the next one, which knocks down the one after that, all the way down the line. However, sometimes a domino fails to knock the next one down. In that case, we have to knock it down by hand to get the dominos falling again. Your task is to determine, given the layout of some domino tiles, the minimum number of dominos that must be knocked down by hand in order for all of the dominos to fall.
Input
The first line of input contains one integer specifying the number of test cases to follow. Each test case begins with a line containing two integers, each no larger than 100 000. The first integer n is the number of domino tiles and the second integer m is the number of lines to follow in the test case. The domino tiles are numbered from 1 to n. Each of the following lines contains two integers x and y indicating that if domino number x falls, it will cause domino number y to fall as well.
Output
For each test case, output a line containing one integer, the minimum number of dominos that must be knocked over by hand in order for all the dominos to fall.
SAMPLE INPUT
1
3 2
1 2
2 3
SAMPLE OUTPUT
1
code completes at 2.1
#include <iostream>
#include <vector>
#include <unordered_set>
#include <stack>
using namespace std;
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv, stack<int> &stk){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current, stk);
}
stk.push(sv);
}
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current);
}
}
int main()
{
int t;
cin>>t;
while(t--){
int V, E;
cin>>V>>E;
vector<vector<int>> edges(V+1);
unordered_set<int> visited;
stack<int> stk;
while(E--){
int f, s;
cin>>f>>s;
edges[f].push_back(s);
}
for(int i=1;i<=V;i++)
if(visited.find(i)==visited.end())
dfs(edges, visited, i, stk);
visited.clear();
int count{0};
while(!stk.empty()){
int current = stk.top();
stk.pop();
if(visited.find(current)==visited.end()){
dfs(edges, visited, current);
count++;
}
}
cout<<count<<endl;
}
return 0;
}
Efficient Code completes at 0.7 sec.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void dfs( vector<int> *edges , int start,int n,bool *visit ,stack<int> *nodex)
{
visit[start] = true;
// cout<<start<<endl;
for (int i = 0; i < edges[start].size(); ++i)
{
int next = edges[start][i];
if(visit[next] == false)
dfs(edges,next,n,visit,nodex);
}
nodex->push(start);
}
void dfs(vector<int> *edges,int start, bool *visit,int n)
{
visit[start] = true;
for(int i=0;i<edges[start].size();i++)
{
int next = edges[start][i];
if(visit[next]==false)
dfs(edges,next,visit,n);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
vector<int> *edges = new vector<int>[n+1];
for (int i = 0; i < m; ++i)
{
int start,end;
cin>>start>>end;
edges[start].push_back(end);
}
// cout<<"PHASE 1"<<endl;
bool *visit = new bool[n+1];
for (int i = 0; i<=n; ++i)
{
visit[i] = false;
}
stack<int> *nodex = new stack<int>();
for (int i = 1; i<=n; ++i)
{
if(visit[i] == false)
dfs(edges,i,n,visit,nodex);
}
// cout<<"PHASE 2"<<endl;
for(int i=0;i<=n;i++)
visit[i] = false;
int count=0;
while(!nodex->empty())
{
int up = nodex->top();
nodex->pop();
// cout<<" EVERYTHING ISS FINE "<<up<<endl;
if(visit[up] ==false )
{
dfs(edges,up,visit,n);
count++;
}
// cout<<"Everrything is fine "<<up<<endl;
}
cout<<count<<endl;
}
return 0;
}
Use Fast I/O and "\n"in place of endl. This helps a lot in getting rid of TLE. For me the rest of the code seems to be fine

Equal elements in an unsorted array

I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other
bool pair(const int array[])
{
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
}
Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?
edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.
I was not trying to compile the code, for the record.
It will do neither:
i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.
If you really cant sort the array (which would be so easy with std::sort) then you can do this:
const int NumCards = 9; // If this is a constant, this definition should occur somewhere.
bool hasPair(const int array[], const int arraySize) {
int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set
// the array elements to 0.
// Iterate over all of the cards in your hand.
for (int i = 0; i < arraySize; i++) {
int myCurrentCard = array[i]; // Get the current card number.
// Increment it in the array.
possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1;
// Or the equivalent to the above in a single line.
possibleCards[array[i]]++; // Increment the card so that you
// count how many of each card is in your hand.
}
for (int i = 0; i < NumCards; ++i) {
// If you want to check for a pair or above.
if (possibleCards[i] >= 2) { return true; }
// If you want to check for exactly a pair.
if (possibleCards[i] == 2) { return true; }
}
return false;
}
This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.
do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array
#include <iostream>
using namespace std;
int* CheckForPairs(int[], int, int&);
int main()
{
int array[ ]= {2, 5, 5, 7, 7};
int nPairsFound = 0;
int* ptrPairs = CheckForPairs(array, 5, nPairsFound);
for(int i(0); i < nPairsFound; i++)
{
cout << ptrPairs[i] << endl;
}
if(ptrPairs)
{
delete[] ptrPairs;
ptrPairs = NULL;
}
return 0;
}
int* CheckForPairs(int array[] , int size, int& nPairsFound)
{
int *temp = NULL;
nPairsFound = 0;
int j = 0;
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
nPairsFound++;
}
temp = new int[nPairsFound];
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
{
temp[j] = i;
j++;
}
}
return temp;
}
You could use a std::unordered_set for a O(n) solution:
#include <unordered_set>
using namespace std;
bool hasMatchingElements(const int array[], int arraySize) {
unordered_set<int> seen;
for (int i = 0; i < arraySize; i++) {
int t = array[i];
if (seen.count(t)) {
return true;
} else {
seen.insert(t);
}
}
return false;
}
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.
You need a nested for loop:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int unsortedArray[] = {2,3,2,4,5};
int size = 5;
for(int i=0;i<size-1;i++)
{ for(int j=i+1;j<size;j++)
{ if(unsortedArray[i]==unsortedArray[j])
{ printf("matching cards found\n");
return 0;
}
}
}
printf("matching cards not found\n");
return 0;
}
----EDIT------
Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:
#include <iostream>
#include <stdio.h>
#include <stdbool.h>
#defin NUM_CARDS 52;
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int N,i,j;
cin>>N;
int unsortedArray[N];
for(int i=0;i<N;i++)
cin>>unsortedArray[i];
int count[NUM_CARDS]={0};
int cnt = 0;
for( i=0;i<N-1;i++)
{
for( j=i+1;j<N;j++)
{ if(unsortedArray[i]==-1)
break;
if(unsortedArray[i]==unsortedArray[j])
{
unsortedArray[j]=-1;
cnt++;
}
}
if(unsortedArray[i]!=-1)
{
count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
// determine the poker hand.
if(cnt==1)
cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else if(cnt>=2)
cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else
cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;
cnt = 0;
}
}

BinSearch fails after Bubble Sort

My program seems to be behaving oddly all of a sudden and I cannot figure out why no matter how I look.
Let's begin with the header
//inventoryData.h
//This is the second edition of inventory data, now featuring an actual description
//This header will load an array, sort it, and then be used in InventorySearch to produce parts and prices.
//by Robert Moore on [DATE]
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
class InventoryData{
//Variables
private:
int partNum[1000];
double price[1000];
int invCount;
public:
InventoryData();//Build Up
void loadArrays(); //Feed the data from the database into our arrays
void arraySort(); //Bubblesort for the array
int seqSearch(int); //Our one by one search method
int binSearch(int); //The other search
int returnpart(int); //Return Part Number
double returnPrice(int); //Return price
//Incorportate a search counter to both these searches?
//IE: bin search found [x] (completed after [y] records)
};
InventoryData::InventoryData()
{
//Load the array
invCount = 0;
for (int count = 0; count < 1000; count++)
{
partNum[count] = 0;
price[count] = 0;
}
}
void InventoryData::arraySort()
{
int counter = 0; //Used to keep track of subscripts
int temp = 0; //Used to sort subscript contents
double tempPrice = 0;
int maxSub = invCount;
int lastKnown = 0; //Used to indicate what the last swapped value was
char swap = 'Y'; //used to indicate if a swap was made or not
while (swap == 'Y')
{
swap = 'N';
counter = 0;
while (counter < maxSub){
if (partNum[counter] < partNum[counter+1])
{
//Swap the part number
temp = partNum[counter];
partNum[counter] = partNum[counter+1];
partNum[counter+1] = temp;
//Swap the price
tempPrice = price[counter];
price[counter] = price[counter+1];
price[counter+1] = tempPrice;
//Report the swap occured
swap = 'Y';
lastKnown = counter;
}
counter++;
}//End of While Loop
maxSub = lastKnown;
}//End this While Loop Too
cout<<"File sort complete."<<endl;
}
void InventoryData::loadArrays()
{
ifstream partIn;
partIn.open("masterInventory.dat");
cout<<"Loading..."<<endl;
if (partIn.is_open())
{
//Prime Read
partIn >> partNum[invCount]
>> price[invCount];
//cout<<partNum[invCount]<<" and "<<price[invCount] <<" have been loaded."<<endl;
while(!partIn.eof())
{
invCount++;
partIn >> partNum[invCount]
>> price[invCount];
// cout<<partNum[invCount]<<" and "<<price[invCount] <<" have been loaded."<<endl;
} //END While
partIn.close();
cout<<"All files loaded successfully."<<endl;
} //END IF*/
else
{
invCount = -1;
cout<<"File failed to open."<<endl;
}
//arraySort();
}
int InventoryData::seqSearch(int searchKey)
{
int index = 0;
int found = -1;
int counter = 0;
while(index < invCount)
{
counter++;
if (searchKey == partNum[index]
)
{
found = index;
index = invCount;
}
else
{
index++;
}
}
cout<<"(Sequential completed after reading "<< counter<<" files.)"<<endl;
return found;
}
int InventoryData::binSearch(int searchKey)
{
int first = 0;
int last = invCount;
int found = 0;
int mid = 0;
int counter = 0;
while (first <= last && found == 0)
{
counter++;
mid = (first + last)/2;
if (searchKey == partNum[mid] ){
found = 1;
return mid;
}
else
{
if (partNum[mid] < searchKey)
{
first = mid+1;
}
else
{
last = mid - 1;
}
}
}
if (found == 0)
{
mid = -1;
}
cout<<"(Binary completed after reading "<< counter <<" files.)"<<endl;
return mid;
}
int InventoryData::returnpart(int value)
{
return partNum[value];
}
double InventoryData::returnPrice(int value)
{
setprecision(2);
return price[value];
}
With this set up, the program loads numbers from a database (any random combination of digits and another set of "prices"), then we call the function to load, sort, and search the array, as found in the CPP file
//InventorySearch
/*This file is used to search our databases
and return a value for whatever our search may
be looking for.*/
//by Robert Moore
#include "inventoryData.h"
#include <iomanip>
int main()
{
//Declare Variable
int tempSeq = 0;
int tempBin = 0;
int search = 0;
char confirmation = 'Y';
int searchCounter = 0;
int partsFound = 0;
int partsLost = 0;
//Build Object and Load Array
InventoryData invent;
invent.loadArrays();
invent.arraySort();
//Introduction
cout<<"Welcome to Part Search."<<endl;
//Begin Loop Here
while(confirmation != 'N')
{
cout<<"Please enter a part number: ";
searchCounter++;
cin>>search;
cout<<endl;
tempSeq = invent.seqSearch(search);
if (tempSeq != -1)
{
std::cout << std::fixed;
cout<<"Sequential found part number "<<invent.returnpart(tempSeq)<< ", and it's price is "<<setprecision(2)<<invent.returnPrice(tempSeq)<<endl;
partsFound++;
}
else
{
cout<<"Sequential search failed to find part number "<<search<<endl;
partsLost++;
}
tempBin = invent.binSearch(search);
if (tempBin != -1)
{
std::cout << std::fixed;
cout<<"Binary found part number "<<invent.returnpart(tempBin)<<", and it's price is "<<setprecision(2)<<invent.returnPrice(tempBin)<<endl;
partsFound++;
}
else
{
cout<<"Binary search failed to find part number "<<search<<endl;
partsLost++;
}
cout<<"Would you like to search again? (Plese enter Y/N): ";
cin>>confirmation;
confirmation = toupper(confirmation);
}
cout<<"Today's Summary: "<<endl;
cout<<setw(5)<<"Total searches: "<<setw(25)<<searchCounter<<endl;
cout<<setw(5)<<"Total successful searches:"<<setw(15)<<(partsFound/2)<<endl;
cout<<setw(5)<<"Total unsuccessful searches:"<<setw(12)<<(partsLost/2)<<endl;
cout<<"Thank you for using Part Search. Have a nice day."<<endl;
return 0;
}
However, the output runs into the following problem: where the sequential search will scour the entire database and find our value, the binSearch will only search up to 8 values and fail. At first I thought this was due to the way the sort was loaded, but once I coded it out, it continued to fail. Worse yet, aside from adding the sort, the program function just fine prior to this.
I'm running out of ideas as to where the program is wrong, as this code worked just fine up until arraySort() was added.
In your arraySort() method, you should take note of the fact that for instance if maxSub=10, then for the part where you write
while (counter < maxSub){
if (partNum[counter] < partNum[counter+1])
{
.....
}
}
you might end up performing
if(partNum[9]<partNum[10]){
....
}
Since C++ does not perform bound checking on arrays, your code, although buggy, might end up compiling successfully, and may (or may not) produce the correct result. Thus you need to change the loop condition to
while((counter+1)<maxSub){
.....
}
Besides, your arraySort() is sorting in the Descending order, and your binSearch() has been implemented for an array sorted in ascending order. You can change either of the methods as per your requirement.
Hope this helps.
Your sorting algorithm seems faulty to me. If you are trying bubble sort, sorting implementation should be like this.
for(int counter1 = 0;counter1<invCount; ++counter1)
{
for(int counter2 = counter1+1; counter2<invCount; ++counter2)
{
if(partNum[counter1] < partNum[counter2])
{
//do swaping here.
}
}
}

Strange output produced by program

I think that my code works. However, it outputs 01111E5, or 17B879DD, or something like that.
Can someone please tell me why.
I am aware that I set the limit of P instead of 10,001. My code is like that because I start with 3, skipping the prime number 2.
#include <iostream>
bool prime (int i)
{
bool result = true;
int isitprime = i;
for(int j = 2; j < isitprime; j++) ///prime number tester
{
if(isitprime%j == 0) result = false;
}
return result;
}
int main (void)
{
using namespace std;
int PrimeNumbers = 1;
int x = 0;
for (int i = 3 ; PrimeNumbers <=10000; i++)
{
if(prime(i))
{
int prime = i;
PrimeNumbers +=1;
}
}
cout<<prime<<endl;
system ("pause");
return 0;
}
cout<<prime<<endl;
prints the address of the function bool prime (int i), not the variable you declared. Just rename the function or the variable (note that you'll also have to change its scope, or move the cout inside the loop - that's if you want to print them all):
for (int i = 3 ; PrimeNumbers <=10000; i++)
{
if(prime(i))
{
cout << i << endl;
PrimeNumbers++;
}
}
Also:
for(int j = 2; j < isitprime; j++) ///prime number tester
{
if(isitprime%j == 0) result = false;
}
could be optimized, since (1) you don't need to check all numbers till isitprime, but at most to sqrt(isitprimt) and (2) you only need to check until result is false, at which point you can break out of the loop.
The output isn't strange at all.
cout<<prime<<endl;
You're printing the function pointer of prime here.
You were probably intending to print the variable you create here:
int prime = i;
But this is in the loop scope. In fact, if you compile with warnings enabled, your compiler should tell you that this variable is never used. Also, it's bad practice to give variables in C or C++ the same name as functions (or any other variable in a higher level scope).
Your loop in the main program does not stop correctly because the test variable, PrimeNumbers may not change.
Try:
for (int i = 3; i < 10000; i++)
{
//...
}
Also, because you declared the variable prime inside an if statement, it disappears after the if statement is executed:
if (prime(i))
{
int prime = i; // <-- Declare the variable before the for loop.
//...
The code for finding prime number from nth to 2(1 is neither prime nor composite) is written below, i havent used math.h header file , did something different and surpizingly it works pretty cool....
Code is:
#include<iostream.h>
#include<stdio.h>
#include<conio.h>
class prime
{
int a;
int i;
public:
void display();
};
void prime::display()
{
cout<<"Enter the number to see primes less than it till 2";
cin>>a;
int count=0;
for(int j=a;j>=1;j--)
{
for(int i=1;i<=j;i++)
{
if(j%i==0)
{
count++;
}
}
if(count==2)
{
cout<<"\t"<<j;
}
count=0;
}
}
void main()
{
clrscr();
prime k;
k.display();
getch();
}
if you want to find the prime number from 1 to n,hope this will help u.
#include <iostream>
#include <vector>
static bool _isprime (int number)
{
if(number==1)
{
return false;
}
bool flag=true;
if(number==2||number%2!=0)
{
for(int i=2;i<number;i++)
{
if(number%i==0)
{
flag=false;
}
}
}
else flag=false;
return flag;
}
int main (void)
{
using namespace std;
vector<int> primenumber;
cout<<"prime number between 1 and ?"<<endl;
int x=0;
cin>>x;
for(int i=0;i<=x;i++)
{
if(_isprime(i)==true)
{
//cout<<x<<" is a prime number"<<endl;
primenumber.push_back(i);
}
//else cout<<x<<" is not a prime number"<<endl;
}
for(int i=0;i<primenumber.size();i++)
{
cout<<primenumber[i]<<endl;
}
cout<<"the number of prime number is "<<primenumber.size()<<endl;
system("pause");
return 0;
}

N Queens in C++ using vectors

I'm having trouble understanding backtracking, I can conceptually understand that we make a move, then if no solutions can be found out of it we try the next solution.
With this in mind I'm trying to solve the N Queens problem,
I'm finding out all the possible candidates that can be placed in the next row and then trying them one by one, if a candidate doesn't yield a solution, I pop it off and go with the next one.
This is core of the code that I have come up with :
void n_queens(int n)
{
vector<int> queens = vector<int>();
backtrack(queens,0,n);
}
void backtrack(vector<int>& queens, int current_row, int N)
{
// check if the configuration is solved
if(is_solution(queens, N))
{
print_solution(queens,N);
}
else
{
// construct a vector of valid candidates
vector<int> candidates = vector<int>();
if(construct_candidates(queens,current_row,N,candidates))
{
for(int i=0; i < candidates.size(); ++i)
{
// Push this in the partial solution and move further
queens.push_back(candidates[i]);
backtrack(queens,current_row + 1,N);
// If no feasible solution was found then we ought to remove this and try the next one
queens.pop_back();
}
}
}
}
bool construct_candidates(const vector<int>& queens, int row, int N, vector<int>& candidates)
{
// Returns false if there are no possible candidates, we must follow a different
// branch if this so happens
for(int i=0; i<N; ++i)
{
if(is_safe_square(queens,row,i,N))
{
// Add a valid candidate, this can be done since we pass candidates by reference
candidates.push_back(i);
}
}
return candidates.size() > 0;
}
It doesn't print anything for any input that I give it. I tried running it through gdb but with no success, I think that is because there is a problem with my fundamental understanding of backtracking.
I have read up about backtracking in a couple of books and also an online tutorial and I still feel hazy, it'd be nice if someone could give me ideas to approach this and help me understand this slightly unintuitive concept.
The entire compilable source code is :
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// The method prototypes
void n_queens(int n);
void backtrack(vector<int>&, int current_row, int N);
bool construct_candidates(const vector<int>&, int row, int N, vector<int>&);
bool is_safe_square(const vector<int>&, int row, int col, int N);
bool is_solution(const vector<int>&, int N);
void print_solution(const vector<int>&, int N);
int main()
{
int n;
cin>>n;
n_queens(n);
return 0;
}
void n_queens(int n)
{
vector<int> queens = vector<int>();
backtrack(queens,0,n);
}
void backtrack(vector<int>& queens, int current_row, int N)
{
// check if the configuration is solved
if(is_solution(queens, N))
{
print_solution(queens,N);
}
else
{
// construct a vector of valid candidates
vector<int> candidates = vector<int>();
if(construct_candidates(queens,current_row,N,candidates))
{
for(int i=0; i < candidates.size(); ++i)
{
// Push this in the partial solution and move further
queens.push_back(candidates[i]);
backtrack(queens,current_row + 1,N);
// If no feasible solution was found then we ought to remove this and try the next one
queens.pop_back();
}
}
}
}
bool construct_candidates(const vector<int>& queens, int row, int N, vector<int>& candidates)
{
// Returns false if there are no possible candidates, we must follow a different
// branch if this so happens
for(int i=0; i<N; ++i)
{
if(is_safe_square(queens,row,i,N))
{
// Add a valid candidate, this can be done since we pass candidates by reference
candidates.push_back(i);
}
}
return candidates.size() > 0;
}
bool is_safe_square(const vector<int>& queens, int row, int col, int N)
{
for(int i=0; i<queens.size(); ++i)
{
// case when the queens are already placed in the same row or column
if(queens[i] == row || queens[i] == col) return false;
// case when there is a diagonal threat
// remember! y = mx + c for a diagonal m = 1 therefore |x2 - x1| = |y2 - y1|
if(abs(i - row) == abs(queens[i] - col)) return false;
}
//Returns true when no unsafe square is found
//handles the case when there are no queens on the board trivially
return true;
}
bool is_solution(const vector<int>& queens, int N)
{
return queens.size() == N;
}
void print_solution(const vector<int>& queens, int N)
{
for(int i=0; i<N; ++i)
{
for(int j=0; j<N; ++j)
{
if(queens[i] == j){ cout<<'Q'; }
else { cout<<'_'; }
}
cout<<endl;
}
}
It's not a fundamental problem, it's just a bug.
In is_safe_square, change
queens[i] == row
to
i == row