#include <stdio.h>
#include <stdlib.h>
/*--------------------八个皇后----------------------*/
#define QUEEN_NUM 8
int label[QUEEN_NUM][QUEEN_NUM]={
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
void AllClear()
{
for(int i=0;i<QUEEN_NUM;++i)
for(int j=0;j<QUEEN_NUM;++j)
label[i][j]=0;
}
void PrintResult()
{
for(int i=0;i<QUEEN_NUM;++i)
{
for(int j=0;j<QUEEN_NUM;++j)
printf("%d ",label[i][j]);
printf("\n");
}
printf("-------------------------------------------\n");
}
int getColumnIndexForLine(int line)
{
int* p_line=label[line];
int index=0;
while (p_line[index] ==0 && index<8)
{
index+=1;
}
if (p_line[index] ==1)
{
return index;
}
else
{
return -1;
}
}
bool CheckOK(int endLineIndex)
{
for (int line=0;line<=endLineIndex;line++)
{
int cloumn=getColumnIndexForLine(line);
if (cloumn>=0)
{
for (int i=0;i<=endLineIndex;i++)
{
if (i!=line && label[i][cloumn]==1)
{
return false;
}
}
}
else
{
printf("line %d has no 1!!!\n",line);
PrintResult();
system("pause");
return false;
}
}
return true;
}
void main()
{
int resultCount=0;
int idx[8];
for (idx[0]=0;idx[0]<8;idx[0]++)
{
label[0][idx[0]]=1;
for (idx[1]=0;idx[1]<8;idx[1]++)
{
label[1][idx[1]]=1;
if(!CheckOK(1)){
label[1][idx[1]]=0;
continue;
}
for (idx[2]=0;idx[2]<8;idx[2]++)
{
label[2][idx[2]]=1;
if(!CheckOK(2))
{
label[2][idx[2]]=0;
continue;
}
for (idx[3]=0;idx[3]<8;idx[3]++)
{
label[3][idx[3]]=1;
if(!CheckOK(3))
{
label[3][idx[3]]=0;
continue;
}
for (idx[4]=0;idx[4]<8;idx[4]++)
{
label[4][idx[4]]=1;
if(!CheckOK(4))
{
label[4][idx[4]]=0;
continue;
}
for (idx[5]=0;idx[5]<8;idx[5]++)
{
label[5][idx[5]]=1;
if(!CheckOK(5))
{
label[5][idx[5]]=0;
continue;
}
for (idx[6]=0;idx[6]<8;idx[6]++)
{
label[6][idx[6]]=1;
if(!CheckOK(6))
{
label[6][idx[6]]=0;
continue;
}
for (idx[7]=0;idx[7]<8;idx[7]++)
{
label[7][idx[7]]=1;
//check ...
if(!CheckOK(7))
{
label[7][idx[7]]=0;
continue;
}
else
{
resultCount+=1;
PrintResult();
}
label[7][idx[7]]=0;
}
label[6][idx[6]]=0;
}
label[5][idx[5]]=0;
}
label[4][idx[4]]=0;
}
label[3][idx[3]]=0;
}
label[2][idx[2]]=0;
}
label[1][idx[1]]=0;
}
label[0][idx[0]]=0;
}
printf("resultCount=%d\n",resultCount);
}
//
// 8!=40320
//
#include<stdio.h>
#include<windows.h>
#define N 8 //可以根据N来修改棋盘的格数
int count = 0;//设置一个计数器
int chess[N][N] = {0};//用于存放棋盘的二维数组
/*
整体思路:
创建一个全局变量的二维数组chess;
并初始化全为0
一行一行开始放皇后;
若存在相互攻击,则皇后向右移一列
若不存在攻击,进行下一行皇后的放置(这里要用到递归)
要点:
(1)国际象棋的格数
国际像是是8*8,因此,如果放置八个皇后,那么每一行都有一个
(2)问题具体化
利用二维数组,用1来代表皇后,其他为0
(3)皇后的放置方法
利用循环,判断位置是否可以放置皇后,若可以,则放置(将其置1)
*/
void print()//打印函数
{
int i = 0;
int j = 0;
printf("*****************************************\n");
for(i = 0; i<N ;i++)
{
for(j = 0; j<N ; j++)
{
printf("%d ",chess[i][j]);
}
printf("\n");
}
printf("*****************************************\n");
}
//判断是否会互吃
//关键条件
//返回1 表示存在互吃
//返回0 表示正常
int check(int i, int j)//i = 7,j = 4
{
if(i == 0)
return 0;//表示正常
int k = 0;
for(k = 0; k<i ; k++)
{
if(chess[k][j] == 1)//(0,4)(1,4)...
return 1;
}
for( int s = 0,k = j+1; k<N ;k++)
{
//(7,4)(6,5),(5,6),(4,7)
if(chess[i-s-1][k] == 1)//(0,11),(1,10),(2,9),(3,8),(4,7)
return 1;
s++;
}
for(k = 0; k<j ;k++)
{
if(chess[i-k-1][j-k-1] == 1)//(6,3)(5,2)(4,1)(3,0)
return 1;
}
for(k = 0; k<N ; k++)
{
if(chess[k][j]==1)
return 1;
}
return 0;
}
//判断棋盘上是否有一行存在没有皇后的情况
//返回0 ,表示棋盘正常(每一行都有皇后)
//返回1 ,表示棋盘有错
int check_all()
{
int i = 0;
int j = 0;
int flag = 0;
for(i = 0; i<N ;i++)
{
flag = 0;
for(j = 0; j<N ; j++)
{
if(chess[i][j]==1)
{
flag = 1;
break;
}
}
if(flag == 0)
return 1;//有错
}
return 0;
}
//检查某一行是否存在皇后
//返回0 表示存在
//返回1 表示没皇后
int check_line(int line)
{
if(line==0)
return 0;
int k = 0;
int s = 0;
int flag = 1;
for(s = 0; s<line-1 ; s++)
{
flag = 1;
for(k = 0; k<N ;k++)
{
if(chess[s][k]==1)
flag = 0;
}
if(flag==1)
return 1;
}
return 0;
}
//递归的主要算法
void queen(int i,int j)
{
//符合,置一,进入下一行
if(check_line(i)==1)//若该行有皇后,返回
return ;
if((i==(N-1)))//若此时是最后一行
{
if(check(i,j)==0)//当最后一行的皇后可以放下(表示可以成功放置)
{
chess[i][j] = 1;//将该位置1,表示皇后
print();//打印
count++;//计数器+1
}
}
if(check(i,j)==0)//当可以放皇后时
{
chess[i][j] = 1;//放入
//print();
//Sleep(1000);
queen(i+1,0);//进行下一行的皇后放置
}
if(j==N)//如果j等于列数,表明越界,返回
return ;
chess[i][j] = 0;//将该位置0
//print();
//Sleep(500);
//不符合,置零,右诺
queen(i,j+1);//将该行皇后右移一位
}
int main(void)
{
queen(0,0);
printf("\ncount = %d\n",count);
return 0;
}
//count = 95
//--------------------------------------
//利用函数递归,解决八皇后问题
//
// zssure 2014-03-12
//--------------------------------------
/*
思路分析
其实该问题并不难,利用递归方法很容易解决。
没放置一个皇后,就将其能够攻击的区域进行标记,
然后放置下一个皇后,一次类推……;
此外,如果有解最终肯定是每一行有且只有一位皇后,
所以放置的时候按照逐行放置的顺序进行。
此问题难点在于如何把控递归函数的返回条件,
一种条件是8个皇后放置完成后,返回成功,
一种条件是该行中已经没有可以放置的位置,
此时返回失败,需要重新放置。此时要额外注意,
所谓的“重新放置”指的并不是将所有皇后清除重新来过,
而是只返回上一层,将上一个导致本次放置失败的皇后进行清除,
然后重新更新其位置,通过逐级放置、
或逐级回溯可以达到遍历所有情况找到所有解
(下文中给出的自己的代码的计算结果不是独立解的个数,
而是所有可行解的情况)
*/
#include <stdio.h>
#include <cmath>
int count=0;//全局计数变量
/*--------------------四个皇后----------------------*/
//#define QUEEN_NUM 4
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,
// 0,0,0,0,
// 0,0,0,0,
// 0,0,0,0 };
/*--------------------五个皇后----------------------*/
//#define QUEEN_NUM 5
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,
// 0,0,0,0,0,
// 0,0,0,0,0,
// 0,0,0,0,0,
// 0,0,0,0,0 };
/*--------------------六个皇后----------------------*/
//#define QUEEN_NUM 6
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,0,
// 0,0,0,0,0,0,
// 0,0,0,0,0,0,
// 0,0,0,0,0,0,
// 0,0,0,0,0,0,
// 0,0,0,0,0,0
// };
/*--------------------七个皇后----------------------*/
//#define QUEEN_NUM 7
//int label[QUEEN_NUM][QUEEN_NUM]={ 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0,
// 0,0,0,0,0,0,0
// };
/*--------------------八个皇后----------------------*/
#define QUEEN_NUM 8
int label[QUEEN_NUM][QUEEN_NUM]={0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0};
void FillChessbox(int m,int n,int num)
{
for(int i=0;i<QUEEN_NUM;++i)
for(int j=0;j<QUEEN_NUM;++j)
if(abs(i-m)==abs(j-n))//对角区域填充
{
if(label[i][j]==0)
label[i][j]=num;
}
int i=0,j=0;
while(i<QUEEN_NUM)//行填充
{
if(label[i][n]==0)
label[i][n]=num;
++i;
}
while(j<QUEEN_NUM)//列填充
{
if(label[m][j]==0)
label[m][j]=num;
++j;
}
}
void ClearChessBox(int m,int n,int num)
{
for(int i=0;i<QUEEN_NUM;++i)
for(int j=0;j<QUEEN_NUM;++j)
if(abs(i-m)==abs(j-n) && label[i][j]==num)
label[i][j]=0;
int i=0,j=0;
while(i<QUEEN_NUM)
{
if(label[i][n]==num)
label[i][n]=0;
++i;
}
while(j<QUEEN_NUM)
{
if(label[m][j]==num)
label[m][j]=0;
++j;
}
}
void AllClear()
{
for(int i=0;i<QUEEN_NUM;++i)
for(int j=0;j<QUEEN_NUM;++j)
label[i][j]=0;
}
void PrintResult()
{
for(int i=0;i<QUEEN_NUM;++i)
{
for(int j=0;j<QUEEN_NUM;++j)
printf("%d ",label[i][j]);
printf("\n");
}
}
bool EightQueen(int n/*皇后个数*/,int c/*已经放置的皇后个数*/)
{
//static int count=0;
//小于3x3的棋盘是无解的
if(n<4)
return false;
for(int i=0;i<n;++i)
{
if(label[c-1][i]==0)//存在可以放置第c个皇后的位置
{
label[c-1][i]=c+1;
if(c==n)/*已经放置完毕所有的皇后*/
{
++count;
PrintResult();
printf("**************************\n");
ClearChessBox(c-1,i,c+1);
//AllClear();
return true;
}
FillChessbox(c-1,i,c+1);
EightQueen(n,c+1);
ClearChessBox(c-1,i,c+1);
/*-------------------------------------------------------------------------------------------------------------------------
// 现场恢复,无论下一个皇后是否顺利放置,都应该恢复现场。原因是
//
// 如果下一个皇后放置失败,那么自然应该将本次放置的皇后去除,重新放置,所以需要进行现场恢复(即回溯);
// 如果下一个皇后放置成功,意味着本次放置已经满足条件,是一个解,此时需要恢复现场,进行下一次的重新放置,寻找下一个解。
//
//------------------------------------------------------------------------------------------------------------------------*/
//if(!EightQueen(n,c+1))
// ClearChessBox(c-1,i,c+1);
}
}
return false;
}
int main()
{
EightQueen(QUEEN_NUM,1);
printf("%d\n",count);
return 0;
}
//92