八皇后问题 复习笔记

八皇后问题

问题简述

一个8x8的棋盘,放置8个棋子,要求任意两个棋子不能处于同一列或同一行或同一斜线上,问有多少种摆法。

简单思路

1.编码: 计算中表示一个现实世界的符号本质都是0,1。那就是用0,1以及它的组合来表示现实里的行为操作符号等。试想如果我们人为去操作,那就是放置一个棋子在第一行第一列,然后逐个试验,我们可以将放置一个棋子在第一行第一列这种情况(行为或符号)为1,第一行第二列为2,这样每一行每一格都有一个唯一的标识,这样就是64个数,所以就是从64个数中任选8个,对应的排列组合中的组合,也就是C(64,8),这就是人工放置的集合总数。

列举组合的所有情况

八皇后问题 复习笔记_第1张图片

当然到这我们意识到问题严重性了;这种集合数量上几十亿了,另谋他法。

在分析一下,其实一行从8个选一个;剩下只能从7个选,问题就变成8的阶乘了,但是集合还是很大。

这里设想下,我们可以用一个8位数来表示,每位数表示某一行的某一列,比如个位数2,就表示第一行放置在第二列上,以此类推。可能这里有人觉得是怎么想到这种方式的呢,其实编码最基本的翻译方式就是 数字了,之后才是数组列表这类。 所以其实很多问题,二维线性的都可以考虑用数字来编码。 那我们这里就用8位数来表示这个 8x8 的棋盘了。

遍历不用从0 开始,变量也不用按1自增

static void main(string[] args)
{
	int sum = 0;
	for(int i = 12345678; i < 87654321;i+=9)
	{
		if(CheckEachNum(i) == 0)
		{
			continue;
		}

		if(CheckNumDia(i) == 0)
		{
			continue;
		}
		sum++;
		Console.WriteLine(i)
	}
	Console.WriteLine(sum)
}

2.约束条件

检测行列是否唯一,那就是检测8位数,每位是不是都是唯一的,可以用计数数组太处理

static int CheckEachNum(int i)
{
	int flag = 1;
	int[] temp = new int[8];
	int j = 0;
	while(i>0)
	{
		temp[i%10] += 1;
		i / 10;
		j++;
	}	
	for(j = 0; j < 8; j++)
	{
		if(temp[j] != 1)
		{
			flag = 0;
			break;
		}
	}
	
	return flag;
}

检查斜线是否一致。那就是考虑斜率是否为1

static int CheckNumDia(int i)
{
	int flag = 1;
	int j = 0;
	int[] temp = new int[8];
	while(i > 0)
	{
		temp[j] = i % 10;
		i / 10;
		j++;
	}
	for(j = 8; j > 0; j--)
	{
		for(int k = j-1; k>0; k--)
		if(Math.abs(temp[j] - temp[k]) = Math.abs(j - k))
		{
			flag = 0
			break;
		}
	}
	
	return flag;
}

回溯法

LeetCode

你可能感兴趣的:(笔记)