习题:八皇后问题

题目
八皇后问题,在 8×8 的国际象棋棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法,并打印每一种摆法。


解题思路
习题:八皇后问题_第1张图片
判断方法:
从上向下依次每行摆放一个皇后,这样就不需要判断一行中是否会不止一个皇后。
在摆放时判断一个位置是否可以摆放皇后:
1.黄色线上只能有一个皇后;对于黄色线上的任意两个方格坐标 (i, j) 、(row, col) 满足 row - i = col -j 。
2.蓝色线上只能有一个皇后;对于蓝色线上则是 row + col = i + j 。
3.同一列只能有一个。

摆放过程:
在添加过程中,每一行都从左向右摆放,当冲突时就摆下一列,如果不冲突就在这个位置摆上皇后,然后去摆下一行;如果这一列摆完也没有找到不冲突的位置,就回退到上一行,将皇后向右移一列。
不断循环上述过程,当最后一行也摆放上皇后之后,这时候就找到一种摆法了。


代码实现:
使用二维数组

#include 

//判断位置row、col是否可以放下皇后
int judge(int queens[][8], int row, int col)
{
     
	for(int i=0; i<row; i++)
	{
     //在摆放row,col位置时,0~row-1行已经摆放过
		for(int j=0; j<8; j++)
		{
     // 二维数组元素为1表示已经摆放了皇后
			if(row-i == col-j && 1 == queens[i][j])
			{
     //黄色斜线
				return 0;
			}
			if(row+col == i+j && 1 == queens[i][j])
			{
     //蓝色斜线
				return 0;
			}
		}
		if(1 == queens[i][col])
		{
     //同一列只能摆放一个
			return 0;
		}
	}
	return 1;
}

int judge1(int queens[][8], int row, int col)
{
     
	for(int i=1; row-i >= 0 && col-i >= 0; i++)
	{
     //黄色斜线
		if(1 == queens[row-i][col-i])
		{
     
			return 0;
		}
	}
	for(int i=1; row-i>=0 && col+i<8;i++)
	{
     //蓝色斜线
		if(1 == queens[row-i][col+i])
		{
     
			return 0;
		}
	}
	for(int i=0; i<row; i++)
	{
     //同一列
		if(1 == queens[i][col])
		{
     
			return 0;
		}
	}
	return 1;
}

//打印摆放方法
void showqueens(int queens[][8], int n)
{
     
	printf("------------------------\n");
	for(int i=0; i<8; i++)
	{
     
		for(int j=0; j<8; j++)
		{
     
			printf("%d ", queens[i][j]);
		}
		printf("\n");
	}
	printf("------------------------\n");
}

//打印所有摆放方法,并返回方法个数
int putqueens(int queens[][8], int n)
{
     
	int i=0, j=0;//当前需要摆放的位置
	int cnt=0;//方法个数
	while(1)
	{
     
		if(judge(queens, i, j))
		{
     //(i, j)可以摆放
			queens[i][j] = 1;//1表示已经摆放了
			i++;//摆放下一行
			j=0;//摆放下一行时从第一列开始摆放
		}
		else
		{
     //(i, j)不可以摆放
			j++;//摆放下一列
		}
		while(8 == j)
		{
     //当i行没有一个位置能够摆放时
			i--;//去i-1行
			for(int m=0; m<8; m++)
			{
     
				if(1 == queens[i][m])
				{
     
					queens[i][m] = 0;//0表示没有摆放皇后
					j = m+1;//将i-1行的皇后像后移一位
				}
			}
		}
		if(8 == i)
		{
     //如果已经摆放了8个皇后
			showqueens(queens, 8);//打印摆法
			cnt++;//摆法方法+1
			do{
     
				i--;//去i-1行找下一种的摆法
				for(int m=0; m<8; m++)
				{
     
					if(1 == queens[i][m])
					{
     
						queens[i][m] = 0;
						j = m+1;
					}
				}
			}while(8 == j);
		}
		if(-1 == i)
		{
     //所有方法都找到时
			return cnt;
		}
	}
}

int main()
{
     
	int q[8][8]={
     };
	int m = putqueens(q, 8);
	printf("%d\n", m);
	return 0;
}

一维数组
这里用一个长度为 8 的一维数组实现,数组元素值的范围是0~7,对应二维数组的列,queens[row] = col 表示(row, col) 这个位置有一个皇后。

#include 

int judge(int queens[], int row, int col)
{
     
	for(int i=0; i<row; i++)
	{
     
		if(col == queens[i] || row-i == col-queens[i] || row+col == i+queens[i])
		{
     
			return 0;
		}
	}
	return 1;
}

int show(int queens[], int n)
{
     
	for(int i=0; i<n; i++)
	{
     
		printf("%d ", queens[i]);
	}
	printf("\n");
}

int putqueens(int queens[], int n)
{
     
	int i=0, j=0;
	int cnt=0;
	while(1)
	{
     
		if(judge(queens, i, j))
		{
     
			queens[i] = j;
			i++;
			j=0;
			if(i == n)
			{
     
				show(queens,8);
				cnt++;
				do{
     
					i--;
					j = queens[i] + 1;//j可能超过最大值
				}while(j == n);
			}
		}
		else
		{
     
			j++;
			while(j == n)
			{
     
				i--;
				j = queens[i] + 1;
			}
		}
		if(-1 == i)
		{
     
			return cnt;
		}
	}
}

int main()
{
     
	int q[8] = {
     };
	int n = putqueens(q, 8);
	printf("%d\n", n);
	return 0;
}

结果总共有92种。

你可能感兴趣的:(习题:八皇后问题)