Finding square made of 1's in a 2D array/matrix - c

Thanks for helping. I really appreciate it. I Have been searching for solution on SO, but nothing is exactly what I need. I need it in C.
My task is to find "largest square" of 1's in an array. The array consists of only 0's and 1's and looks, for example, like this:
4 4
0 1 1 1
0 1 0 1
0 1 1 1
1 0 1 0
Output should print [row][col] of "upper left corner" 1, and [row][col] of "lower right corner", So it should be, for my example, [0][1] and [2][3].
I am using my getcolor() function to get value on [row][col] spot.
Also, I have these functions to get longest horizontal and vertical lines. For some reason they only work with arrays with the same number of columns and rows. When I use, for example, an array with 4 cols and 5 rows, it does not work right. Aan you help me please?
void getHline(Bitmap *arr)
{
int i, j, k;
int line, line_start, line_end, line_max = 0;
// Horizontally
for (k = 0; k < arr->rows; k++)
{
for (i = 0; i < arr->rows; i++)
{
if(!getcolor(arr, k, i))
{
continue;
}
for(j = i; j < arr->cols; j++)
{
if(!getcolor(arr, k, j))
{
break;
}
}
j--;
if(j - i + 1 > line_max)
{
line = k;
line_start = i;
line_end = j;
line_max = line_end-line_start+1;
}
}
}
printf("horizontally\n");
printf("start: [%d][%d]\n", line_start, line);
printf("end: [%d][%d]\n", line_end, line);
}
void getVline(Bitmap *arr)
{
int i, j, k;
int col, col_start, col_end, col_max = 0;
for(k = 0; k < arr->cols; k++)
{
for (i = 0; i < arr->rows; i++)
{
if (!getcolor(arr,i,k)) continue;
for (j = i; j <arr->cols; j++)
{
if (!getcolor(arr,j,k)) break;
}
j--;
if (j - i + 1 >col_max)
{
col = k;
col_start = i;
col_end = j;
col_max = col_end-col_start+1;
}
}
}
printf("\nverticaly\n");
printf("start: [%d][%d]\n", col, col_start);
printf("end: [%d][%d]\n", col, col_end);
}

If you're trying to get the largest square this has noting to do with the longest horizontal and vertical lines, because they could be separated and no square associated with them.
When trying to solve a complex problem, don't try to solve it all at once.
The first thing we have, is that each point of the array is associated with a square (the largest one for each point). So we have to find that square: We take a point of the array, then we move by steps through a continuous horizontal and vertical lines. For each step we check if we get a square and repeat the process until we get the largest square associated with that single point.
Each time we get the largest square associated with a point we check if it's largest than the last largest square associated with some previous point.
After connecting these parts we get our final program.
Explanation of the variables used in the program:
Link to the program http://pastebin.com/Yw05Gbtg or view it here:
EDIT:
#include <stdio.h>
main()
{
int lines=4, cols=4;
int arr[4][4] = {
{0,1,1,1,},
{0,1,0,1,},
{0,1,1,1,},
{1,0,1,0,}
};
int x_start, y_start, x_end, y_end, d_max=0;
int i, j, k, l;
int col_start, line_start, col_end, line_end, checker;
for (y_start=0; y_start<lines; y_start++){
for (x_start=0; x_start<cols; x_start++){
x_end = x_start;
y_end = y_start;
for (i=x_start, j=y_start; i<cols && j<lines; i++, j++){ // moving horizontally and vertically
if (!arr[y_start][i] || !arr[j][x_start]){ // checking if the horizontal or vertical lines are not continuous
break;
}
else {
checker = 1;
for (k=x_start, l=y_start; k<i+1 && l<j+1; k++, l++){ // check if square
if (!arr[j][k] || !arr[l][i]){
checker = 0;
break;
}
}
if (checker){ // if square then
x_end = i;
y_end = j;
}
}
}
if ((x_end-x_start)>d_max){
col_start = x_start;
line_start = y_start;
col_end = x_end;
line_end = y_end;
d_max = col_end-col_start;
}
}
}
printf("The largest square is:\n[%d][%d] x [%d][%d]\n", line_start, col_start, line_end, col_end);
// this is only to check if the program is working properly
for (y_start=line_start; y_start<line_end+1; y_start++){
printf("\n ");
for (x_start=col_start; x_start<col_end+1; x_start++){
printf("%d ", arr[y_start][x_start]);
}
}
printf("\n");
}

There is confusion between rows and cols somewhere in your code. To find it, rename your variables i, j and k to something more meaningful, like row, col_start and col_end.
As for finding maximal square, you might want to use prefix sums.

Related

How can i print the pattern given below (rhombus shape) in C?

Expected output:
I have already printed the rhombus shape but I cant get it to print this number pattern (1 232 34543...)
Here is my code.
If anyone can help me I would appreciate it very much.
Thanks in advance.
int main()
{
int i, j, rows;
int stars, spaces;
printf("Enter rows to print : ");
scanf("%d", &rows);
int a;
stars = 1;
spaces = rows - 1;
/* Iterate through rows */
for(i=1; i<rows*2; i++)
{
/* Print spaces */
for(j=1; j<=spaces; j++)
printf(" ");
/* Print stars */
for(j=1; j<stars*2; j++){
printf("*");
}
/* Move to next line */
printf("\n");
if(i<rows)
{
spaces--;
stars++;
}
else
{
spaces++;
stars--;
}
}
getch();
return 0;
}
I did not put my answer to let you figure it out, but since there is already one I show how I did it too. It seems to work. (Only the changed part).
for(j=1; j<stars*2; j++){
if (j < stars)
if (i < rows) // upper left triangle
printf("%c", '0' + ((j + i - 1) % 10));
else // lower left triangle
printf("%c", '0' + ((j + rows * 2 - i - 1) % 10));
else
if (i < rows) // upper right triangle
printf("%c", '0' + (2 * stars - j + i - 1) % 10);
else // lower right triangle
printf("%c", '0' + (2 * stars - j + rows * 2 - i - 1) % 10);
}
Making a bit more compact and getting rid of the "character mentallity" in the printf.
for(char c, j = 1; j < stars * 2; j++) {
if (j < stars)
c = i < rows ? (j + i - 1) : (j + rows * 2 - i - 1);
else
c = i < rows ? (2 * stars - j + i - 1) : (2 * stars - j + rows * 2 - i - 1);
printf("%d", c % 10);
}
Actually there are only two parts that need to be changed. (Since other people have posted answers)
Note: the following solution requires some knowledge on the absolute value function.
First, before the forloop, you declare another variable which stores the value of rows
int totalRows = rows;
then, inside the forloop, change your printf("*"); to the following:
printf("%d",(stars - abs(j-stars) -1 + totalRows - abs(totalRows - i)) %10);
Let me break it down into two sections: row wise and column wise.
Row wise:
When we look at each row, we can see that the number is increasing starting at index 0 until it reaches the center (at index stars), then it starts to decrease. This is the shape of an inverted absolute value function shifted upward. The -1 is to account for starting at index 0 instead of index 1.
stars - abs(j-stars) -1
prints a shape of
This accounts for the increments and decrements in the rows
Column wise:
When we look at each column, we see a similar pattern: the number increases starting at index 1 until center, then it starts to decrease. Another shape of inverted absolute function shifted upward.
row - abs(row - i)
This accounts for the increments and decrements in the columns
When you combine the two together, and take mod 10 (which only keeps the last digit). You get the desired output
printf("%d",(stars - abs(j-stars) -1 + totalRows - abs(totalRows - i)) %10);
//totalRows has the initial value of rows
I found one solution to your problem as below...
#include <stdio.h>
int main()
{
int i, j, k, x, rows, half_row=1;
int stars, spaces;
printf("Enter rows to print : ");
scanf("%d", &rows);
int a;
stars = 1;
spaces = rows - 1;
/* Iterate through rows */
for(i=1; i<rows*2; i++)
{
/* Print spaces */
for(j=1; j<=spaces; j++)
printf(" ");
/* Print numbers */
if(rows >= i){ /* Print First Half */
x = i;
for(k=0;k<i;k++){
if(x>=10){
x=x%10;
}
printf("%d", x);
x++;
}
x--;
for(k=1;k<i;k++){
x--;
printf("%d", x);
if(x==0){
x=10;
}
}
}
else{ /* Print Second Half */
x--;
for(k=1;k<=i-(2*half_row);k++){
if(x==10){
x=0;
}
printf("%d", x);
x++;
}
x--;
for(k=1;k<=i-(2*half_row)-1;k++){
x--;
printf("%d", x);
if(x==0){
x=10;
}
}
half_row++;
}
/* Move to next line */
printf("\n");
if(i<rows)
{
spaces--;
stars++;
}
else
{
spaces++;
stars--;
}
}
getch();
return 0;
}

C language. How to find the maximum minimum. (2D arrays)

I have written code that allows you to enter one dimension of a NxN double array. It will then print random numbers in a 2D array and it finds the maximum and minimum number of each row. It then prints them and their coordinates (row and column).
ATTENTION!!!!
I have altered my code in such a way that it finds the minimum number of the maximum. I now don't know how to find it's coordinates
My code is as follows:
int N, i, j, min=1000, max, m , o;
time_t t;
int masyvas[100][100], minmax[100];
printf("Enter one dimension of a NxN array\n");
scanf("%d", &N);
srand((unsigned) time(&t));
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
masyvas[i][j] = rand() % 10;
printf("%4d", masyvas[i][j]);
}
printf("\n");
}
int k, l, idkeymax, idkeymin;
for(k=0; k<N; k++)
{
max=-1000;
for(l=0; l<N; l++)
{
if(max<masyvas[k][l])
{
max=masyvas[k][l];
}
}
minmax[k]=max;
}
for(m=0; m<N; m++)
{if(minmax[m]<min)
min=minmax[m];
}
printf("maziausias skaicius tarp didziausiu yra %d eiluteje %d stulpelyje %d\n",min);
Here's the pseudo code of what you need to do.
for row in grid {
row_max = max_in_row(row)
grid_min = min(grid_min, row_max)
}
Step one is to write a routine that finds the max and location in a list. You could do this as one big function, but it's much easier to understand and debug in pieces.
You also need the index where it was found. Since C can't return multiple values, we'll need a struct to store the number/index pair. Any time you make a struct, make routines to create and destroy it. It might seem like overkill for something as trivial as this, but it will make your code much easier to understand and debug.
typedef struct {
int num;
size_t idx;
} Int_Location_t;
static Int_Location_t* Int_Location_new() {
return calloc(1, sizeof(Int_Location_t));
}
static void Int_Location_destroy( Int_Location_t* loc ) {
free(loc);
}
Now we can make a little function that finds the max number and position in a row.
static Int_Location_t* max_in_row(int *row, size_t num_rows) {
Int_Location_t *loc = Int_Location_new();
/* Start with the first element as the max */
loc->num = row[0];
loc->idx = 0;
/* Compare starting with the second element */
for( size_t i = 1; i < num_rows; i++ ) {
if( row[i] > loc->num ) {
loc->num = row[i];
loc->idx = i;
}
}
return loc;
}
Rather than starting with some arbitrary max or min, I've used an alternative technique where I set the max to be the first element and then start checking from the second one.
Now that I have a function to find the max in a row, I can now loop over it, get the max of each row, and compare it with the minimum for the whole table.
int main() {
int grid[3][3] = {
{10, 12, 15},
{-50, -15, -10},
{1,2,3}
};
int min = INT_MAX;
size_t row = 0;
size_t col = 0;
for( size_t i = 0; i < 3; i++ ) {
Int_Location_t *max = max_in_row(grid[i], 3);
printf("max for row %zu is %d at %zu\n", i, max->num, max->idx);
if( max->num < min ) {
min = max->num;
col = max->idx;
row = i;
}
Int_Location_destroy(max);
}
printf("min for the grid is %d at row %zu, col %zu\n", min, row, col);
}
I used a different technique for initializing the minimum location, because getting the first maximum would require repeating some code in the loop. Instead I set min to the lowest possible integer, INT_MAX from limits.h which is highest possible integers. This allows the code to be used with any range of integers, there are no restrictions. This is a very common technique when working with min/max algorithms.

Graph Coloring in C: Unable to identify the logical error

I am trying to implement the graph coloring algorithm in C, this implementation is based on how we assign the colors by iterating through the adjacency matrix. I am unable to get it after assigning a color to the second vertex.
Here is the code of my program:
int n, a[10][10], i, j, k, c[10], max = 0, col, ct = 0, rt = 0, m, count = 2;
void main() {
printf("enter n\n");
scanf("%d", &n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n", n, n);
for (i = 0; i < n; i++) {
c[i] = 0;
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
}
c[0] = 1;
c[1] = 2;
for (i = 1; i < n; i++) {
for (j = 0; j < n; j++)
if (a[i][j] > 0) {
m = 0;
for (col = 0; col < n; col++) {
if (a[i][col] > 0)
rt++;
if (a[col][i] > 0)
ct++;
}
m = rt;
if (ct > rt)
m = ct;
if (m < 2) {
if (a[0][i] > 0)
c[i] = 2;
else
c[i] = 1;
} else {
c[i] = count;
if (m > max) {
max = m;
count++;
}
}
rt = 0;
ct = 0;
}
if (c[i] < 1)
if (c[i - 1] > 1)
c[i] = 1;
else
c[i] = 2;
}
printf("The proper coloring is\n");
for (i = 0; i < n; i++)
printf("c%d=%d ", i + 1, c[i]);
printf("\n");
}
Example Input:
Consider a complete graph:
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
Expected output:
c1=1 c2=2 c3=3 c4=4
Observed output:
c1=1 c2=2 c3=3 c4=3
The error seems to be in logic, as you may have inferred by the looks of the question title. The conditional statement where you are checking if m is greater than max and then updating max and count accordingly seem to be incorrect.
I could not exactly figure out what the intended logic was, but I can tell why it is incorrect.
In your usage, you keep the maximum number of neighbors you encountered in max, and update it when you find a vertex which has more neighbors. With it, you also update count, which I think holds the color of currently highest value. Now, unless you encounter a vertex with more neighbors at each step(while traversing each row), you don't update max, and therefore you don't update count. Consequently, unless you encounter such a vertex, you keep assigning the same currently highest count to all vertices you encountered.
You should explain some more about the algorithm you implemented. However, just by looking at your code I think you should at least increment count somewhere different.
A good idea might by just keeping an array equal to the number of vertices. Then for each vertex (inside outermost loop) you can reset the array and by traversing all of the neighbors of ith vertex you can set the colors used in them, and pick the smallest unused color.
It is probably not the most efficient way to do it, but you already have an O(n3) algorithm, so I think it wouldn't hurt going this way.
Below is your code, updated to reflect the changes I mentioned.
int n,a[10][10],i,j,k,c[10],max=0,col,ct=0,rt=0,m,count=2;
int used[11]; /* indices used are from 1 to n, inclusive */
void main()
{
printf("enter n\n");
scanf("%d",&n);
printf("enter the Adjacency Matrix for %d rows and %d columns\n",n,n);
for(i=0; i < n ; i++)
{
c[i]=0;
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
c[0]=1;
c[1]=2;
for(i = 1 ;i < n;i++)
{
for(j = 1 ;j <= n ;j++)
used[j] = 0;
for(j = 0 ;j < i ;j++)
{
if(a[i][j] > 0)
used[c[j]] = 1;
}
for(j = 1 ;j <= n ;j++)
if(!used[j])
{
c[i] = j;
break;
}
}
printf("The proper coloring is\n");
for(i = 0;i < n ;i++)
printf("c%d=%d ",i+1,c[i]);
printf("\n");
}
What does a straightforward algorithm to colour the verices look like?
Consider all vertices in a loop and assign a colour. Vertices that have been visited already have a colour; vertices that will still be visited are still uncoloured.
Determine which colours are used by adjacent vertices that have already been coloured.
With this information, pick the lowest possible colour.
What does your algorithm look like:
Assign colour 1 to vertex 1 and colour 2 to vertex 2. (Note that vertex 2 can use the same colour as vertex 1 if the two aren't connected.)
Loop over all remaining vertices; then loop over all vertices cnnected to that.
Count the number of incoming and outgoing links to the second vertex in yet another loop. (Note that merely counting the links doesn't give you information on which colours are still available. You could have many vertices coloured with colours 3 and 4, for example, but you base your new colour on the number of links. In this example, colour 1 would be a good choice.)
Your criterion for chosing a new colour is whether the number of links is greater or equal to 2. You then assign the count, but before incrementing it. That gives you the second 3 in your example, where there should be a 4.
So you loop once too many and have a poor criterion for choosing a colour. Instead of counting the lonks, you should keep a list of used colours in adjacent nodes and base your new colour on that list.
Other stylistic issues with your code:
All your variables should be local to main; there's no reason to make them global, especially since you don't use functions.
Please be more systematic with your variable declarations. To have them all slapped together in one large definition, which even claoesces arrays and scalars, make them hard to understand.
Please use braces around all code blocks, even if they are not strictly necessary. It makes reading the code easier. Small if s without an else in the inner block such as if (ct > rt) m = ct; don't need braces, but consider using them everywhere else.

Transfering a 2-dimensional array into a single dimension array

I'm trying to make a program in C that transfers a 2-dimensions-array(a matrix to be particular) into a single-dimension-array. For example, if we have a matrix with L lines and C columns, it should turn into a a single line newL=L*C. Therefore, if the matrix has 3 lines and 4 columns, the new array will have 3*4=12 as its size.
The matrix should turn to this:
1 2
--> 1 2 3 4
3 4
The problem I'm facing right now, is how to assign the matrix to the array without having random values or repeated values.
The piece of code I'm concerned with, goes like this:
for(k=1;k<=t;k++)
{
for(i=1;i<=l;i++)
{
for(j=1;j<=c;j++)
{
v[k]=m[i][j];
}
}
}
k,i and j are counters of the matrix(2-dimensions-array) and the the array. two of which; i and j, are counters for the matrix and k is the array's counter. Notice that each one of them starts from 1 and goes to its size and in this size I will use 2 lines and 2 columns for the matrix therefore the array will have a size of 4(2*2).
l is the number of lines in the array.
c is the number of colunms in the array.
t is the size of the array. t=l*c
Executing the code gives me this as a return:
1 2
--> 4 4 4 4
3 4
Simply said, the piece of code will ALWAYS give the last value of the matrix to the array. So if I replace 4 with 5 in the matrix, the array will have 5 5 5 5.
EDIT:
Here is the full code to understand what I'm trying to do:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c,i,j,l,k,t;
printf("Donner le nombres des lignes: ");
scanf("%d",&l);
printf("Donner le nombres des colonnes: ");
scanf("%d",&c);
int m[l][c];
t=l*c;
int v[t];
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
printf("Donner m[%d][%d]: ",i+1,j+1);
scanf("%d",&m[i][j]);
}
}
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
printf("%d\t",m[i][j]);
}
printf("\n");
}
printf("\n\n\n\n");
for(k=1;k<=t;k++)
{
for(i=1;i<=l;i++)
{
for(j=1;j<=c;j++)
{
v[k]=m[i][j];
}
}
}
for(k=0;k<t;k++)
{
printf("%d\t",v[k]);
}
system("pause");
}
Thank you guys for the help, I found the correct way to do it.
You need not the outer loop
Array indices are zero-based in C
Thus, we have:
for(k = 0, i = 0; i < o; i++)
{
for(j = 0; j < p; j++)
{
v[k++] = m[i][j];
}
}
where o and p - dimensions of the matrix m
If we have a multidimensional array like this:
int nums[3][3];
And we have:
int all[9];
And we've got:
int a, b;
We'll reference each of the nums like this:
nums[a][b];
Now think of what the values of a and b will actually be:
for (a = 0; a < 3; a++) {
for (b = 0; b < 3; b++)
all[((a * 3) + b)] = nums[a][b];
}
This will work so long as you multiply a with the number of elements it will iterate:
int nums[5][5];
int all[25];
int a, b;
for (a = 0; a < 5; a++) {
for (b = 0; b < 5; b++)
all[((a * 5) + b)] = nums[a][b];
}
You mention your question is "how to I fix the code?" I think plenty of people have given you the correct answer. This is your code along with the corrected code.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c,i,j,l,k,t;
printf("Donner le nombres des lignes: ");
scanf("%d",&l);
printf("Donner le nombres des colonnes: ");
scanf("%d",&c);
int m[l][c];
t=l*c;
int v[t];
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
printf("Donner m[%d][%d]: ",i+1,j+1);
scanf("%d",&m[i][j]);
}
}
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
printf("%d\t",m[i][j]);
}
printf("\n");
}
printf("\n\n\n\n");
/* corrected code below */
k = 0;
for(i=0;i<l;i++)
{
for(j=0;j<c;j++)
{
v[k]=m[i][j];
k++;
}
}
/* corrected code above */
for(k=0;k<t;k++)
{
printf("%d\t",v[k]);
}
system("pause");
}
As long as the new array is the correct size, something like the following should work:
k=0;
for(i=0;i<l;i++){
for(j=0;j<c;j++){
v[k]=m[i][j];
k++;
}
}
Essentially, you are traversing over the matrix (your lines and columns--as you put it) and at the same time increasing the position (k) in the new array where you want that value to be put.
This:
for(k=1;k<=t;k++)
for(i=1;i<=l;i++)
for(j=1;j<=c;j++)
v[k]=m[i][j];
does not do what you think. Think about when you first loop through the j part, you will be setting all the 0th element of v the entire time, finally the last value you set will stick (ie, the one in position 1, 1 which happens to be 4). Then you will increment k to 1 and repeat it again, resulting in all 4's. You want this:
for(i = 0; i < l; i++)
for(j = 0; j < c; j++)
v[i*l+j] = m[i][j]; // i*l + j gives you the equivelent position in a 1D vector.
Make sure your v vector is the right size ie. int v[l*c];. Also remember that in c zero indexing is used.If you really do need 1 based indexing (which you dont ...) then do this:
int k = 1;
for(i = 1; i <= l; i++)
for(j = 1; j <= c; j++)
v[k++]=m[i][j];
But remember that this will make any further operations on this vector Gross. So dont do this ....
If you just want to access the matrix elements as a single dimension array, you could declare an int pointer v:
int m[3][4];
int *v = (int*)m;
// then access for example m[1][1] as v[5]
Or, to actually copy the array, use a double for (as in the other answers), a single for like below
int vv[12];
for(i = 0; i < 12; i++)
vv[i] = m[i/4][i%4];
or just use memcpy:
memcpy(vv, m, 12*sizeof(int));

Wrong output with the N Queen

So I have to do a modified version of the N queen problem, where we are given an initial configuration of the chess board filled with pawns, and we need to find the maximum number of queens we can have so that they don't attack each other. The input consists of an integer in the first line giving the dimension of the board ( NxN) and n lines defining the setup of the chess board.The characters will be either a ā€˜pā€™ (meaning there is already a pawn in that location) or an ā€˜eā€™ (meaning that location is empty).
For example, for this input,
5
epepe
ppppp
epepe
ppppp
epepe
the output will be 9.
Here is my code, everything seems clear, but I don't see why it doesnt give the correct output
#include <stdio.h>
#include <malloc.h>
/* function headers */
void do_case(int);
int solve(char **,int,int);
int canPlace(char **,int,int,int);
/* Global vars */
int queens;
int main(void)
{
int n;
scanf("%d",&n);
getchar();
while( n != 0 )
{
do_case(n);
scanf("%d",&n);
getchar();
}
return 0;
}
void do_case(int n)
{
int i,j; //counters for input
//board configuration allocation
char **configuration = (char **)malloc(n*sizeof(char *));
for(i = 0 ; i < n ;i++ )
configuration[i] =(char *)malloc(n*sizeof(char));
queens = 0;
//get input
for( i = 0; i < n; i++ )
{
for( j = 0; j < n; j++ )
{
scanf("%c",&configuration[i][j]);
}
getchar();
}
//solve
solve(configuration,n,0);
printf("%d \n",queens);
}
//recursive solver
int solve(char **configuration,int N,int col)
{
int i,j;
//base case
if( col >= N )
return 1;
//consider this column
//try placing queen in non blocked spot in all rows
for(i = 0; i < N; i++)
{
if ( configuration[i][col] == 'e' && canPlace(configuration,N,i,col) )
{
//Place queen in configuration[i][col]
configuration[i][col] = 'q';
queens++;
//recursion on the rest
if( solve(configuration,N,col + 1) == 1 )
{
return 1;
}
//backtrack
configuration[i][col] = 'e';
queens--;
}
}
return 0;
}
//this function check if queen can be placed
int canPlace(char **configuration,int N, int row, int col)
{
int i, j;
/* Check this row on left side */
for (i = 0; i < col; i++)
{
if (configuration[row][i] == 'q')
{
return 0;
}
}
/* Check upper diagonal on left side */
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
{
if ( configuration[i][j] == 'q')
{
return 0;
}
}
/* Check lower diagonal on left side */
for (i = row, j = col; j >= 0 && i < N; i++, j--)
{
if (configuration[i][j] == 'q')
{
return 0;
}
}
return 1;
}
Basically, your code outputs 0 because it requires that we place exactly one queen in every column, which is not the case in your example.
That said, there are multiple problems with the algorithm (and I don't claim the list is complete, though it may be):
The code does not consider every possibility: it will only find the first possible arrangement, and then quit searching after a single "if( col >= N ) return 1;". Instead, it should go like "if( col >= N ) update the best possible value of queens in a separate variable, then return 0 to continue searching".
In the line "if( solve(configuration,N,col + 1) == 1 )", the code assumes there can not be two queens in a single column. The call should use col instead of col + 1, and somehow account for where we stopped at the current column.
To allow columns without queens, an unconditional call to "solve(configuration,N,col + 1)" should be placed somewhere in the solve function.
When we allow item 2, the function canPlace should be modified to also check the column.
The loops of canPlace should break whenever a pawn is found.
With pawns blocking the way, you shouldn't just move on to the next column because you can place more queens in the same column. You should modify your code to pass both a row and a column when you recurse, and only move to the next square, not the next column.
Also, it looks like your algorithm finds the first solution instead of the best solution. The original queens problem only cared about 1 possible solution, but with the modified problem, you need to make sure you check all solutions and remember the best one.
Also, your canPlace function is wrong. It doesn't account for pawns at all.

Resources