Reputation: 29
I am trying to solve this Queen problem of placing 4 queen in 4x4 matrix . I know it can be solved with backtracking algorithm . However i have not studied that and i am trying to solve it with my current knowledge . So what i am trying is to generate all possible combination of Queen in 4x4 matrix and print only one which cannot cancel each other .
1) For generating all combination , i am using rand function .
However there is obviously fault in my above coding . There are some outputs with only three '1' instead of four '1' . I am not able to eliminate this problem .
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
main()
{
srand(time(NULL));
int ar[30][30], i , j , a , b , c = -1, d = -1, k = 0;
while (1)
{
for (i = 0 ; i < 4 ; i++)
{
for (j = 0 ; j < 4 ; j++)
{
ar[i][j] = 0;
}
}
for (i = 0 ; i < 2 ; i++)
{
for (j = 0 ; j < 2 ; j++)
{
a = rand() % 3 ;
b = rand() % 3 ;
if (a != c || b != d)
{
ar[a][b] = 1 ; // here 1 = Queen
c = a ;
d = b;
}
}
}
}
}
2) Also is there any way i can reduce the time complexity using only these method ?
Upvotes: 0
Views: 453
Reputation: 25286
The following is the brute force, backtracking code for the 8 queens problem, asked some time ago. Just change 8 to 4:
int checkBoard(int board[8][8]);
int putQueens(int board[8][8], int nQueens);
void printBoard(int board[8][8]);
int eightQueens(void)
{
int board[8][8];
memset(board, 0, sizeof(int)*64);
if (putQueens(board, 0)) {
printBoard(board);
return (1);
}
return(0);
}
int putQueens(int board[8][8], int nQueens)
{
int i, j;
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
if (board[i][j]==0) {
board[i][j]= 1;
if (checkBoard(board)) {
if (nQueens==7) return(1);
if (putQueens(board, nQueens+1)) return(1);
}
board[i][j]= 0;
}
}
}
return(0);
}
int checkBoard(int board[8][8])
{
int i, j;
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
if (board[i][j]) {
int ii, jj;
for (ii=i+1; ii<8; ii++) {
if (board[ii][j]) return(0);
}
for (jj=j+1; jj<8; jj++) {
if (board[i][jj]) return(0);
}
for (ii=i+1, jj=j+1; ii<8 && jj<8; ii++, jj++) {
if (board[ii][jj]) return(0);
}
for (ii=i-1, jj=j-1; ii>0 && jj>0; ii--, jj--) {
if (board[ii][jj]) return(0);
}
for (ii=i-1, jj=j+1; ii>0 && jj<8; ii--, jj++) {
if (board[ii][jj]) return(0);
}
for (ii=i+1, jj=j-1; ii<8 && jj>0; ii++, jj--) {
if (board[ii][jj]) return(0);
}
}
}
}
return (1);
}
void printBoard(int board[8][8])
{
int i,j;
printf(" ");
for (j=0; j<8; j++) printf(" %1d",j+1); printf("\n");
for (i=0; i<8; i++) {
printf("%1d ",i+1);
for (j=0; j<8; j++)
printf(" %1c", board[i][j]==0? '-':'*');
printf("\n");
}
}
Upvotes: 0
Reputation: 29126
(1) You check only that a queen isn't placed on the same square as the last queen you placed. Remove the variables c
and d
and check whether ar[a][b]
is still zero.
(2) Your scatter approach will produce many set-ups that are misses. Especially, because you don't enforce that ther cannot be any queens on the same rank and file. (In addition, rand() % 3
produces random values from 0 to 2, inclusively. You will never get a non-threatening configuration that way.)
If you want to use your random (bogosort) approach, you could use a one-dimensional array where the index is the rank and the number is the file where a queen is. Then you start with:
int queen[4] = {0, 1, 2, 3};
and shuffle the array. For 4 queens, that will yield 4! = 24 possibile configurations. You could try to iterate through them systematically.
Upvotes: 1
Reputation: 108978
Instead of using temporary variables to check whether the array is filled, use the array itself!
for (i = 0 ; i < 2 ; i++)
{
for (j = 0 ; j < 2 ; j++)
{
a = rand() % 3 ;
b = rand() % 3 ;
if (ar[a][b] == 0)
{
ar[a][b] = 1 ; // here 1 = Queen
}
}
}
Your problem is that the inner loop will execute 4 times and you can only control 1 repeat with variables c
and d
.
Let's say a
is 1 and b
is 1: you make c = 1
and d = 1
.
then a
is 2 and b
is 1 ... making c = 2
and d = 1
.
then if a is 1 and b is 1 again, you cannot check for duplicate.
Upvotes: 1