compare function for pairs not working - c++

I have written my own compare function to sort a vector of pairs. My sort function should be like this.
The point (i,j) will be ahead of point(x,y) if it is closer to (5,5), vice-versa. I am finding the distance and then comparing based on that.
The code is
#include<iostream>
#include<stdlib.h>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
double distance(int a, int b, int x, int y)
{
return sqrt(pow(a-x,2.0)+pow(b-y,2.0));
}
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis=distance(i.first, i.second, 5,5);
double dis2=distance(j.first, j.second, 5, 5);
if(dis<dis2)
return i.first< j.first;
return i.first>j.first;
}
int main()
{
int n;
cin>>n;
vector<pair<int, int> > p;
for(int i=0; i < n; i++)
{
int a,b;
cin>>a >>b;
p.push_back(make_pair(a,b));
}
sort(p.begin(),p.end(),mycomp);
for(int i=0; i<n; i++)
cout<<p[i].first<<" "<<p[i].second<<endl;
return 0;
}

You did not specify what you mean by “not working,” so I’ll take that as license to point out anything I like about your code.
Your mycomp routine does not do what you describe. In particular, always make sure that a comparison routine is antisymmetric.
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis=distance(i.first, i.second, 5, 5);
double dis2=distance(j.first, j.second, 5, 5);
if (dis < dis2) {
return true;
}
if (dis2 > dis) {
return false;
}
// tie break
return std::less<decltype(i)>(i,j);
}
If that line with the decltype does not work, you may have to spell the tie break out yourself.

The answer by #ChristopherCreutzig should solve your problem. I'm going to suggest something that will obviate the need for computing a square root.
int square(int a)
{
return a*a;
}
int distanceSquared(int a, int b, int x, int y)
{
return square(a-x) + square(b-y);
}
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis1 = distanceSquared(i.first, i.second, 5, 5);
double dis2 = distanceSquared(j.first, j.second, 5, 5);
if ( dis1 != dis2 )
return (dis1 < dis2);
return (i.first < j.first);
}

This is not the right condition check.
if(dis<dis2)
return i.first< j.first
return i.first>j.first;
Should suffice return dis < dis2;

Related

no matching function for call to a function in merge sort

I am trying to write a merge sort algorithm in C++.
If i try to compile the following code, i get the error:
mergeSort.cpp:9:19: error: no matching function for call to 'merge(std::vector&, int&, int&, int&)'
I tried everything in my knowledge to fix this problem and find similar ones online, but I can't figure it out on my own. Please help!
#include <bits/stdc++.h>
void sort(std::vector<int> v, int a, int b) {
//if a == b the length of the subarray is one
if (a != b) {
int k = (a + b) / 2;
sort(v, a, k);
sort(v, k+1, b);
merge(v, a, k, b); //this line gives out the error
}
}
void merge(std::vector<int> &v, int &a, int &k, int &b) {
std::vector<int> tempv;
int tmpa = a;
int tmpk = k;
for (int i = 0; i < b-a; i++) {
if (tmpa >= k-1) {
tempv.push_back(v[tmpk]);
tmpk++;
}
else if (tmpk >= b) {
tempv.push_back(v[tmpk]);
tmpk++;
}
else if (v[tmpa] < v[tmpk]) {
tempv.push_back(v[tmpk]);
tmpk++;
}
else {
tempv.push_back(v[tmpk]);
tmpk++;
}
}
for (int i = a; i < b; i++) {
v[i] = tempv[i-a];
}
}
int main() {
std::vector<int> v = {2, 7, 1, 3, 4, 4};
sort(v, 0, v.size()-1);
for (int i: v) {
std::cout << i << " ";
}
std::cout << std::endl;
}
You are calling the merge() function before the definition of that, so just shift your merge() function before the sort() function.
Put this line before the sort function:
void merge(std::vector<int> &v, int &a, int &k, int &b);
The declaration of merge is not visible at the point of usage. Declare the function before using it.
// Declare the function.
void merge(std::vector<int> &v, int &a, int &k, int &b);
void sort(std::vector<int> v, int a, int b) {
//if a == b the length of the subarray is one
if (a != b) {
int k = (a + b) / 2;
sort(v, a, k);
sort(v, k+1, b);
// Now you can use it.
merge(v, a, k, b); //this line gives out the error
}
}
On a more imporant note...
sort needs to accepts the vector by reference, not by value. Otherwise, the sorted object won't be visible in the calling function.
void sort(std::vector<int>& v, int a, int b) { ... }
// ^^^
As a matter of good coding practice, I recommend declaring all functions before defining and using them.
// Declare the functions.
void sort(std::vector<int>& v, int a, int b);
void merge(std::vector<int> &v, int &a, int &k, int &b);
// Define the functions.
void sort(std::vector<int>& v, int a, int b)
{
...
}
void merge(std::vector<int> &v, int &a, int &k, int &b)
{
...
}
In C++ you need to make sure the function declaration before it's used.
In your case, you used merge before any declaration and so the error.
To fix that, put this declaration at the front, before it is used in your sort function:
void merge(std::vector<int> &v, int &a, int &k, int &b);
Alternatively, you could move the whole merge function definition up front.
Btw, this code could overflow with the intermediate calculation (a + b)
int k = (a + b) / 2; // could overflow
which could be improved by:
int k = a - (a - b) / 2; // fine

Finding maximum clique with node count and nonadjacent edge list given

I have a task which I have been trying to solve for the last week. It's driving me crazy. The task is:
Given a node count N(1 <= N <= 10`000),
nonadjacent node pair count M(1 <= M <= 200`000)
and the nonadjacent node pairs themselves
M0A, M0B,
M1A, M1B,
...
MM-1A, MM-1B,
find the maximum clique.
I am currently trying all kinds of bron-kerbosch algorithm variations.
But every time I get a time limit on the testing site. I posted the only code that doesn't have a time limit BUT it has a wrong answer. The code is kind of optimized by not creating a new set every recursion.
Anyways, PLEASE help me. I am a desperate latvian teen programmer. I know this problem can be solved, because many people have solved it on the testing site.
#include <set>
#include <vector>
std::map<int, std::set<int> > NotAdjacent;
unsigned int MaxCliqueSize = 0;
void PrintSet(std::set<int> &s){
for(auto it = s.begin(); it!=s.end(); it++){
printf("%d ",*it);
}
printf("\n");
}
void Check(std::set<int> &clique, std::set<int> &left){
//printf("printing clique: \n");
//PrintSet(clique);
//printf("printing left: \n");
//PrintSet(left);
if(left.empty()){
//PrintSet(clique);
if(clique.size()>MaxCliqueSize){
MaxCliqueSize = clique.size();
}
return;
}
while(left.empty()==false){
std::vector<int> removed;
int v = *left.begin();
left.erase(left.begin());
for(auto it2=NotAdjacent[v].begin();it2!=NotAdjacent[v].end();it2++){
auto findResult = left.find(*it2);
if(findResult!=left.end()){
removed.push_back(*it2);
left.erase(findResult);
}
}
clique.insert(v);
Check(clique, left);
clique.erase(v);
for(unsigned int i=0;i<removed.size();i++){
left.insert(removed[i]);
}
}
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> clique, left;
for(int i=1;i<=n;i++){
left.insert(i);
}
Check(clique, left);
printf("%d",MaxCliqueSize);
}
For what it's worth, this code seems to pass 5 tests and I think all the rest exceed either time or memory limits (submitted as C++11). This idea is to find a maximum independent set in the graph complement, for which we readily receive the edges for. The algorithm is what I could understand of the standard greedy one. Perhaps this can give you or others more ideas? I believe there are some improved algorithms for MIS.
#include <iostream>
using namespace std;
#include <map>
#include <set>
#include <vector>
#include <algorithm>
std::map<int, std::set<int> > NotAdjacent;
vector<int> Order;
unsigned int NumConnectedToAll = 0;
unsigned int MaxCliqueSize = 0;
bool sortbyN(int a, int b){
return (NotAdjacent[a].size() > NotAdjacent[b].size());
}
void mis(std::set<int> &g, unsigned int i, unsigned int size){
if (g.empty() || i == Order.size()){
if (size + NumConnectedToAll > MaxCliqueSize)
MaxCliqueSize = size + NumConnectedToAll;
return;
}
if (g.size() + size + NumConnectedToAll <= MaxCliqueSize)
return;
while (i < Order.size() && g.find(Order[i]) == g.end())
i++;
int v = Order[i];
std::set<int> _g;
_g = g;
_g.erase(v);
for (auto elem : NotAdjacent[v])
_g.erase(elem);
mis(_g, i + 1, size + 1);
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> g;
Order.reserve(NotAdjacent.size());
for (auto const& imap: NotAdjacent){
Order.push_back(imap.first);
g.insert(imap.first);
}
sort(Order.begin(), Order.end(), sortbyN);
for (int i=1; i<=n; i++)
if (NotAdjacent.find(i) == NotAdjacent.end())
NumConnectedToAll++;
for (unsigned int i=0; i<Order.size(); i++){
mis(g, i, 0);
g.erase(Order[i]);
}
printf ("%d", MaxCliqueSize);
return 0;
}

How to write a comparator for map and priority_queue where the elements are 2 dimensional array

I am trying to implement A* search for a N puzzle whose size is 15. My start state would be random. The goal state is the des array in the code. I can only swap tiles with 0 (blank state) in 4 directions in the puzzle to create a new state. To implement this I have used a priority_queue and 4 maps. For all of these , I have used 2 dimensional array. Compare is the comparator for the priority_queue and map_cmp is the comparator for the 4 maps. Vis is used to keep track of the visited states, Dis is used to keep count of the path , parent is used to keep the parent of the state and ab is used to keep the position of 0 (blank space) of each state. Here is the code:
enter code here
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
int fx[]={0,0,1,-1};
int fy[]={1,-1,0,0};
int des[4][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11},{12,13,14,15}};
int func1(int node[][4])
{
int cnt=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(i==0 && j==0)
continue;
if(des[i][j]!=node[i][j])
cnt++;
}
}
return cnt;
}
double func2(int node[][4])
{
int a,b,x,y;
double sum=0.0;
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(node[i][j]==0)
continue;
a=node[i][j];
x=a/4;
y=a%4;
sum+=sqrt((i-x)*(i-x)+ (j-y)*(j-y));
}
}
}
struct map_cmp {
bool operator()(const int (&a)[4][4], const int (&b)[4][4]) const {
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
if(a[i][j]!=b[i][j])
return true;
else
continue;
}
}
return false;
}
};
map<int[4][4],int,map_cmp>vis;
map<int[4][4],int,map_cmp>dist;
map<int[4][4],int[][4],map_cmp>parent;
map< int[4][4],pair<int,int>,map_cmp >ab;
struct compare
{
bool operator()(const int (&a)[4][4],const int (&b)[4][4] )const{
return ((dist[a]+func1(a)) < (dist[b]+func1(b)));
}
};
bool isValid(int row, int col)
{
return (row >= 0) && (row < 4) && (col >= 0) && (col < 4);
}
int bfs( int src[][4],int a,int b)
{
int u[4][4];
int v[4][4];
int x,y;
vis[src]=1;
dist[src]=0;
parent[src]={0};
ab[src]=pii(a,b);
pii pos;
priority_queue < int[4][4], vector < int[4][4] > , compare > q;
q.push(src);
while(!q.empty())
{
u = q.top();
q.pop();
pos=ab[u];
for(int i=0;i<4;i++)
{
copy(u,u+16,v);
x=pos.first+fx[i];
y=pos.second+fy[i];
if(isValid(x,y))
{
swap(v[pos.first][pos.second],v[x][y]);
vis[v]=1;
dist[v]=dist[u]+1;
ab[v]=pii(x,y);
parent[v]=u;
if(memcmp(des,v,sizeof(des))==0)
return dist[v];
q.push(v);
}
}
}
}
int main()
{
int a,b,i,j,k,m,n,x,y;
int result[5];
int src[4][4]={{7,2,12,11},{10,14,0,6},{8,13,3,1},{9,5,15,4}};
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(src[i][j]==0)
{
x=i;
y=j;
break;
}
}
if(j!=4)
break;
}
a=bfs(src,x,y);
ab.clear();
}
The errors i am getting are for the comparator of maps and priority_queue.
They are:
1. no match for operator[] in dist[a]/vis/parent/ab[in short all the maps]
2. invalid array assignment
3. no matching function for call to 'std::priority_queue, compare>::push(int (*&)[4])'
This is my first post here. Sorry for any mistakes. Any help will be appreciated as i have already done whatever i can
Leave alone the unsized array issue.
Let's consider about the issue in question title, starting from the definition of std::priority_queue,
std::priority_queue<class _Tp, class _Container, class _Compare>
three parameters are element type, element container(default std::vector), comparator(It's a class with () comparator, default std::less).
class TpType {};
class TpTypeComparatator {
bool operator () (TpType &a, TpType &b) const {
return true;
}
};
std::priority_queue, TpTypeComparatator> q;

Binary addition algorithm

I am trying to implement a code from a standard quotient and remainder algorithm namely:
function divide(x,y)
if x=0: return (q,r)=(0,0)
(q,r)=divide(floor(x/2),y)
q=2*q, r=2*r
if x is odd: r=r+1
if r>=y: r=r-y, q=q+1
return (q,r)
with a c++ code here is the relavent part of my function
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
However this simply does not work for example with BinaryA={1,0,1,1} and BinaryB={0,1}. This is 13/2 so q should be {0,1,1}, and r should be {1}. But my code out puts r={1} and q={0,1}. I don't understand what is going on. All functions that are used above that are not defined work. Also, is there a easier way to return two values in c++ if there is I would be grateful to know. Thank you.
Add is the whole code
#include <iostream>
#include <string> //this is only used for the user to insert a number
#include <stdlib.h> //this is used to convert the user iputed string to a vector
#include <vector>
#include <algorithm>
using namespace std;
void CleanArray(vector<int> & Array){ //CleanArray() is mainly for the Multiply function where we need to keep removing the enteries
for(int i=0;i<Array.size();i++){
Array[i]=0; //of a vector<int> Array. And then I clean some of the other struct vector<int>'s for saft
}
}
vector<int> addBinary(vector<int> A,vector<int> B){ //addBinary() adds two struct vector<int>'s and returns a new struct vector<int>
vector<int> C; // C is our carry array but we take advantage of the fact that after we carry to a new column we nolonger need the old one so we
// can also use C to store our answere.
C.assign(A.size()+1,0);
CleanArray(C);
for(int i=0; i<B.size();i++){ //Case 1 we are adding the first part where we are adding columns and we still have vector<int> A and vector<int> B
if(C[i]+B[i]+A[i]==3){
C[i]=1;
C[i+1]=1;
}
else if(B[i]+A[i]+C[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(B[i]+ A[i]+C[i] ==1){
C[i]=1;
}
}
for(int i=B.size();i<A.size();i++){ //Case 2 we adding where vector<int> B has been exasted and we only have vector<int> A and vector<int> C.
if(C[i]+A[i]==2){
C[i]=0;
C[i+1]=1;
}
else if(A[i]==1){
C[i]=1;
}
} // this is fine but not necessary.
if(C[C.size()-1]==0) // We want to change C's member length_a if the aswere is one bigger then the size of A.size().
C.pop_back();
return C;
}
vector<int> Subtract(vector<int> A, vector<int> B){ // this function is almost exactly the same as Multiply() using a vector<int> C to hold the value of A-B
vector<int> C;
C.assign(A.size(),0);
CleanArray(C);
// reverse(B.begin(), B.end());
for(int i=A.size()-B.size();i>0;i--)
B.push_back(0);
// reverse(B.begin(), B.end());
for(int i=A.size()-1;i>=0;i--){
if((A[i]+B[i])==2)
C[i]=0;
else if(A[i]==1 && B[i]==0)
C[i]=1;
else if(B[i]==1 && A[i]==0){
C[i]=1;
int j=0;
int k=i+1;
while(j==0){ //we need this while loop bc when we have 0-1 this changes all values of
if(C[k]==1){ //C[i+1] to the next C[]==1, changing all of those to 1 so ex 1000-1=0111
C[k]=0;
j++;
}
else if(C[k]==0){
C[k]=1;
k++;
}
// if(i==C.size()-1 && C.size()>1) // this removes the zero's in front of the numberso the answer is not like 001 but 1.
// C.pop_back();
}
}
// else this was the problem with subtraciton
// C[i]=0; "" " " " " "
}
int i=C.size()-1;
while(C[i]==0 && i!=0){
C.pop_back();
i--;
}
return C;
}
vector<int> Multiply(const vector<int> & A, const vector<int> &B){ // This also uses the concept of having a vector<int> C to store the values of the succesive additions of the rows
vector<int> C;
C.assign(A.size(),0);
for(int j=0;j<B.size();j++){
vector<int> D;
D.assign(A.size(),0);
for(int i=0;i<A.size();i++){
if(B[j]==1)
D[i]=A[i];
// this makes a new row if B[j]==1 so if 1110101*1=1110101(0...0) there are j zero's in
}
D.insert(D.begin(),j,0);
C=addBinary(D,C); //this adds the pervious value of C with the next row.
}
return C;
}
void pop_front(vector<int> & A){
reverse(A.begin(),A.end());
A.pop_back();
reverse(A.begin(),A.end());
}
bool compareVector(const vector<int> &A, const vector<int> &B){
if(A.size()<B.size())
return(1==0);
if(A.size()>B.size())
return(1==1);
for(int i=A.size()-1;i>=0;i--){
if (A[i]>B[i])
return(1==1);
if(A[i]<B[i])
return(1==0);
}
return(1==1);
}
struct QandR{
vector<int> r;
vector<int> q;
};
QandR Division(vector<int> BinaryA, const vector<int> & BinaryB, QandR &x){
vector<int> one, zero;
one.clear();
one.push_back(1);
zero.clear();
zero.push_back(0);
if(BinaryA==zero){
return x;
}
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);
x=Division(BinaryA,BinaryB,x);
x.q=addBinary(x.q,x.q);
x.r=addBinary(x.r,x.r);
if(BinaryA[0]==1)
x.r=addBinary(x.r,one);
if(compareVector(x.r,BinaryB))
{
x.r=Subtract(x.r,BinaryB);
x.q=addBinary(x.q,one);
}
return x;
}
/*
vector<int> modexp(vector<int> x,vector<int> y, vector<int> N){
vector<int> one;
vector<int> r;
vector<int> q;
one.push_back(0);
if(y.size()==1 && y[1]==0)
return one;
y.pop_back();
vector<int> z=modexp(x,y,N);
if(y[0]==1){
vector<int> D=Multiply(z,z);
Division(D,N,q,r);
z=q;
return z;
}
else{
vector<int> C =Multiply(Multiply(z,z),x);
Division(C,N,q,r);
z=q;
return z;
}
}
*/
int main(){
int arraya[4]={1,1,0,1};
int arrayb[2]={1,1};
vector<int> a(arraya,arraya+4);
vector<int> b(arrayb,arrayb+2);
for(int i=0;i<a.size();i++){
cout<<a[i]<<" ";
}
cout<<endl;
pop_front(a);
for(int i=0;i<a.size();i++)
cout<<a[i]<<" ";
cout<<endl;
QandR x;
x.r.clear();
x.q.clear();
x.r.push_back(0);
x.q.push_back(0);
x=Division(a,b,x);
for(int i=0;i<x.r.size();i++){
cout<<x.r[i]<<" ";
}
cout<<endl;
for(int i=0;i<x.q.size();i++)
cout<<x.q[i]<<" ";
cout<<endl;
return 0;
}
When you divide BinaryA by 2, and try to call Division again, you have to return BinaryA to its original state so that you can verify if it was odd or not.
So, in these two cases:
else if(BinaryA==one){
BinaryA[0]=0;
}
else if(BinaryA.size()>1)
pop_front(BinaryA);'
you have to keep the bit that is lost and restore it after the recursive Division has returned.

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