Lua学习笔记之八皇后问题

目录

1、博客介绍

2、内容

3、推送

4、结语


1、博客介绍

lua学习笔记之一,Lua版八皇后问题的写法,回溯算法的典型案例,编辑器使用Sublime

注:本篇博客部分源码摘自Lua程序设计(第四版)梅隆魁译


2、内容

--检查(n,c)是否不会被攻击
function isplaceok(a,n,c)
	for i=1,n-1 do
		if (a[i] == c) or           --同一行
			(a[i]-i == c-n) or 		--对角线
			(a[i] + i == c+n) then	--对角线
			return false
		end
	end
	return true --不会被攻击
end

--打印棋盘
function printsolution(a)
	for i=1,8 do
		for j=1,8 do
			io.write(a[i]==j and "X" or "-"," ")
		end
		io.write("\n")
	end
	io.write("\n")
end

function addQueen(a,n)
	if n > 8 then
		printsolution(a)
	else
		for c=1,8 do
			if isplaceok(a,n,c) then
				a[n] = c
				addQueen(a,n+1)
			end
		end
	end
end

addQueen({},1)


-----------------------输出示例
X - - - - - - - 
- - - - X - - - 
- - - - - - - X 
- - - - - X - - 
- - X - - - - - 
- - - - - - X - 
- X - - - - - - 
- - - X - - - - 

内容很简单同学们直接看源码吧,最后一个函数addQueen为核心,运行后将在控制台输出所有符合八皇后规则的排列组合,该解法虽然能够输出所有符合规则的组合,但是我们观察一下核心代码addQueen,相当于从第一列开始每一列每一行都去尝试排列,如果不符合就舍弃之前的内容,这样算是去穷举而不符合回溯的优选法,以下我们对代码略作修改。

-----------------------------回溯算法 输出第一种满足情况

--当前列所处的位置
local colIndexList = {}
--上次回溯记录
local lastSucRow   = 0
-- 检查(n,c)是否不会被攻击
function isplaceok(a,n,c)
	for i=1,n-1 do
		if (a[i] == c) or           --同一行
			(a[i]-i == c-n) or 		--对角线
			(a[i] + i == c+n) then	--对角线
			return false
		end
	end
	return true --不会被攻击
end
--打印棋盘
function printsolution(a)
	for i=1,8 do
		for j=1,8 do
			io.write(a[i]==j and "X" or "-"," ")
		end
		io.write("\n")
	end
	io.write("\n")
end
function addQueen(col,recallTag)
	if col<1 then return end   									--小于1的列不执行
	if recallTag then   										--判断本次执行是否为回溯
		colIndexList[col] = nil									--回溯则当前序列表内值置空						
		if lastSucRow == 8 then									--回溯点已为当前列最大值则继续向前回溯
			lastSucRow = colIndexList[col-1] or 0
			addQueen(col-1,true)
			return
		end
	end
	for i=lastSucRow+1,8 do
		if isplaceok(colIndexList,col,i) then   				--符合要求停止循环
			colIndexList[col] = i
			if col == 8 then									--已够8列则输出
				printsolution(colIndexList)
			else							    				--不够则继续添加
				lastSucRow = 0									--设置回溯点
				addQueen(col+1)
			end	
			break
		else
			if i == 8 then										--改列没有满足的要求
				lastSucRow = colIndexList[col-1] or 0
				addQueen(col-1,true)							--回溯到上一列
			end
		end
	end
end
addQueen(1)

我们稍微改善了一下addQueen的写法,在这里我们新增了两个变量,一个是用来记录当前数据的表colIndexList,另一个则是用来记录回溯点的lastSucRow,addQueen的核心思想就是,我从第一列第一行的数据去开始判断,如果满足八皇后规则的条件则将该点的数据记录在colIndexList内,并且将该店作为回溯点记录,然后去判断下一列的点,如果下一列有满足的点,则继续,没有满足的点就可以回溯到上一列的回溯点去继续判断,若是数据长度到了8则就输出方阵,该写法输出满足条件的第一组数据,我们在稍加改动可以输入任意数量满足规则的数据。

--当前列所处的位置
local colIndexList 			= {}
--上次回溯记录
local lastSucRow   			= 0
local targetSucIndex 		= 100
local sucIndex 				= 0
-- 检查(n,c)是否不会被攻击
function isplaceok(a,n,c)
	for i=1,n-1 do
		if (a[i] == c) or           --同一行
			(a[i]-i == c-n) or 		--对角线
			(a[i] + i == c+n) then	--对角线
			return false
		end
	end
	return true --不会被攻击
end
--打印棋盘
function printsolution(a)
	for i=1,8 do
		for j=1,8 do
			io.write(a[i]==j and "X" or "-"," ")
		end
		io.write("\n")
	end
	io.write("\n")
end
function addQueen(col,recallTag)
	if col<1 then return end   									--小于1的列不执行
	if recallTag then   										--判断本次执行是否为回溯
		colIndexList[col] = nil									--回溯则当前序列表内值置空						
		if lastSucRow == 8 then									--回溯点已为当前列最大值则继续向前回溯
			lastSucRow = colIndexList[col-1] or 0
			addQueen(col-1,true)
			return
		end
	end
	for i=lastSucRow+1,8 do
		if isplaceok(colIndexList,col,i) then   				--符合要求停止循环
			colIndexList[col] = i
			if col == 8 then									--已够8列则输出
				sucIndex = sucIndex + 1
				printsolution(colIndexList)
				if sucIndex < targetSucIndex then				--不够则继续回溯
					lastSucRow = i
					addQueen(col,true)						    --回溯到上一列
				end
			else							    				--不够则继续添加
				lastSucRow = 0									--设置回溯点
				addQueen(col+1)
			end	
			break
		else
			if i == 8 then										--改列没有满足的要求
				lastSucRow = colIndexList[col-1] or 0
				addQueen(col-1,true)							--回溯到上一列
			end
		end
	end
end
addQueen(1)

大家看上述代码当中,我们较前一组代码进行了微小的改动,新增了两个变量targetSucIndex用来确定输出方阵的数量,sucIndex用来记录当前输出数据的数量,我们在addQueen方法中做了改动,本来在满足8数据长度后就会输出并且停止运算,现在改动后,会在满足8长度后,将当前点作为回溯点去继续运算,这样当输出数据数量小于目标数量时就会继续计算,这里注意,满足条件一共有92种,所以你目标数据无论多大,在输出完所有符合规则的数据后依然会停止运算。


3、推送

Github:https://github.com/KingSun5


4、结语

        若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。

       QQ交流群:806091680(Chinar)

       该群为CSDN博主Chinar所创,推荐一下!我也在群里!

猜你喜欢

转载自blog.csdn.net/Mr_Sun88/article/details/105282338