八皇后问题

我在网站上找到了很多的八皇后问题的答案,有些思路非常巧妙,但是对于思路的解释并不详细,所以我就打算自己总结一下八皇后问题,尽可能详细的解释出来。

第一种方法:

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

思路:首先是先建立一个8*8的棋盘格,然后有皇后的用-1表示,没有的用0表示。
然后每次找到一个空位可以放置皇后之后,就把对应的行列对角线做上标记,
如果在某行找不到空位,就把上一行的皇后换位置,同时标记的行列对角线也要取消标记。 
*/ 

#include
//定义一个8*8的棋盘格 
int cheese_table[8][8];
//定义一个数组,纪律每行的皇后在第几列 
int queen[8];
//通过此变量设置search_line函数从哪里开始寻找可以放置皇后的位置 
int lastqueen=-1;
//答案的个数 
int solution=0;
//寻找i行中有没有可以放置皇后的位置,有的话返回j(第几列),没有返回-1。 
int search_line(int i,int j)
{
	//在第i行第j列后有没有可以放置皇后的位置 
	for(;j<8;j++)
	{
		if(cheese_table[i][j]==0)
		{
			return j;
		}
	}
	return -1;
}
//放置皇后,并对与其相关的行、列与对角线进行操作 
void set_queen(int i,int j)
{
	//用-1代表放置了皇后 
	cheese_table[i][j]=-1;
	//记录在第几列 
	queen[i]=j;
	//行操作 
	for(int m=0;m<8;m++)
	{
		if(cheese_table[i][m]!=-1)
		{
			cheese_table[i][m]++;
		}
	}
	//列操作
	for(int m=0;m<8;m++)
	{
		if(cheese_table[m][j]!=-1)
		{
			cheese_table[m][j]++;
		}
	}
	//东北操作
	int tempj=j+1;
	for(int tempi=i-1;tempj<8&&tempi>=0;tempi--)
	{
		cheese_table[tempi][tempj++]++;
	}
	//东南操作
	tempj=j+1;
	for(int tempi=i+1;tempi<8&&tempj<8;tempi++)
	{
		cheese_table[tempi][tempj++]++;
	}
	//西南操作
	tempj=j-1;
	for(int tempi=i+1;tempi<8&&tempj>=0;tempi++)
	{
		cheese_table[tempi][tempj--]++;
	}
	//西北操作
	tempj=j-1;
	for(int tempi=i-1;tempi>=0&&tempj>=0;tempi--)
	{
		cheese_table[tempi][tempj--]++;
	} 
	return;
}

void uptake_queen(int i)
{
	//获取列数,好对行、列与对角线进行操作 
	int j=queen[i];
	//行操作 
	for(int m=0;m<8;m++)
	{
		if(cheese_table[i][m]!=-1)
		{
			cheese_table[i][m]--;
		}
	}
	//列操作
	for(int m=0;m<8;m++)
	{
		if(cheese_table[m][j]!=-1)
		{
			cheese_table[m][j]--;
		}
	}
	//东北操作
	int tempj=j+1;
	for(int tempi=i-1;tempj<8&&tempi>=0;tempi--)
	{
		cheese_table[tempi][tempj++]--;
	}
	//东南操作
	tempj=j+1;
	for(int tempi=i+1;tempi<8&&tempj<8;tempi++)
	{
		cheese_table[tempi][tempj++]--;
	}
	//西南操作
	tempj=j-1;
	for(int tempi=i+1;tempi<8&&tempj>=0;tempi++)
	{
		cheese_table[tempi][tempj--]--;
	}
	//西北操作
	tempj=j-1;
	for(int tempi=i-1;tempi>=0&&tempj>=0;tempi--)
	{
		cheese_table[tempi][tempj--]--;
	}
	cheese_table[i][j]=0;
	return;
}

int main()
{
	//对棋盘进行初始化操作 
	for(int i=0;i<8;i++)
	{
		for(int j=0;j<8;j++)
		{
			cheese_table[i][j]=0;
		}
	}
	//开始放置 
	for(int i=0;;i++)
	{
		//判断有没有可以放置皇后的位置 
		int j=search_line(i,lastqueen+1);
		if(j==-1)
		{
			//如果不能放置皇后且通过回溯也到达了第一行的位置,就说明不能在找到更多的答案了,程序也就结束了 
			if(i==0)
			{
				break;
			}
			//如果不是程序结束,就要回溯,也就是如果第i行没有位置,就是因为第i-1行的位置放置的不对,对i-1行重新放置 
			lastqueen=queen[i-1];
			uptake_queen(i-1);
			//因为每次循环都要i++,所以最终的结果仍是上一行(i-1) 
			i=i-2;
		}
		else
		{
			//放置皇后后,下一行要从头开始判断有没有位置 
			lastqueen=-1;
			//放置皇后 
			set_queen(i,j);
			//当放置到第8行时,就是一个答案,这是要对第8行进行回溯,以防在此位置之后还有位置可以放置 
			if(i==7)
			{
				solution++;
				uptake_queen(7);
				lastqueen=queen[7];
				i--; 
		    }
		}
	 } 
	 std::cout<

其他的之后会再写,因为只理解了这一个(苦笑!!!)

你可能感兴趣的:(数据结构与算法)