A*算法求解N数码
Posted 是一个小迷糊吧
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A*算法求解N数码相关的知识,希望对你有一定的参考价值。
A*算法实验
实验目的:
1.熟悉启发式搜索的定义、估价函数和算法过程
2.利用A*算法求解N数码难题,理解求解流程和搜索顺序
3.熟练掌握numpy库的相关函数(单独库,需要使用‘pip install numpy’安装)
实验原理:
A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价以及从节点n到达目标节点的估价代价。
实验内容:
1 、以8数码问题为例实现A*算法的求解程序。
估价函数f(n) = g(n) + h(n)
g(n)=d(n)——结点n在搜索树中的深度
h(n)可选择h1(n)——结点n中“不在位”的数码个数 或 h2(n) =p(n)= 将牌“不在位”的距离和
代码实现:
import numpy as np
def change (str):#提取输入到数字,合成数组
list=[]
for i in range(0,len(str)):
list.append(str[i])
a = np.array(list)
b = a.reshape(hang,lie)
return b
def h(newnumber,endnumber):#计算两个数码间位置不同的数字的个数
h=0
for i in range(0,hang):
for j in range(0,lie):
if (newnumber[i][j]!=endnumber[i][j]):
h+=1
else:
continue
return h
def g(newnumber,endnumber):#计算每个数字最近的路径之和
g=0
for i in range(0,hang):
for j in range(0,lie):
if (newnumber[i][j]!=endnumber[i][j]):
g+=((abs((i-end[newnumber[i][j]][0])))+(abs((j-end[newnumber[i][j]][1]))))
else:
continue
return g
def kongid(newnumber):#判断空格的位置
for i in range(0,hang):
for j in range(0,lie):
if (newnumber[i][j]==' '):
id=(i,j)
return id
def same(newnumber,endnumber):#比较两个数组是否相等,相等返回True,不相等返回False
a=(newnumber==endnumber)
e=a.all()
if(e):
return True
else:
return False
def A(newnumber,endnumber):#变化N字码
if (same(newnumber,endnumber)):
return True
else:
xx=hang*lie*10
l1n=xx
l2n=xx
l3n=xx
l4n=xx
a=kongid(newnumber)
l1=newnumber.copy()
l2=newnumber.copy()
l3=newnumber.copy()
l4=newnumber.copy()
l0=newnumber[a[0]][a[1]]
if((a[0]-1)>=0):
l1[a[0]][a[1]]=newnumber[a[0]-1][a[1]]
l1[a[0]-1][a[1]]=l0
l1h=h(l1,endnumber)
l1g=g(l1,endnumber)
l1n=l1g+l1h
if((a[0]+1)<=(hang-1)):
l2[a[0]][a[1]]=newnumber[a[0]+1][a[1]]
l2[a[0]+1][a[1]]=l0
l2h=h(l2,endnumber)
l2g=g(l2,endnumber)
l2n=l2g+l2h
if((a[1]-1)>=0):
l3[a[0]][a[1]]=newnumber[a[0]][a[1]-1]
l3[a[0]][a[1]-1]=l0
l3h=h(l3,endnumber)
l3g=g(l3,endnumber)
l3n=l3g+l3h
if((a[1]+1)<=(lie-1)):
l4[a[0]][a[1]]=newnumber[a[0]][a[1]+1]
l4[a[0]][a[1]+1]=l0
l4h=h(l4,endnumber)
l4g=g(l4,endnumber)
l4n=l4g+l4h
return [l1,l2,l3,l4,l1n,l2n,l3n,l4n]
while (True):
str=input("输入要变化的数码问题的顺序(数据自左到右,自上到下):")
str1=input("输入变化后的数码问题的顺序(数据自左到右,自上到下):")
heng=input("输入数码的行数:")
shu=input("输入数码的列数:")
hang=int(heng)
lie=int(shu)
if ((hang*lie)==len(str) and ((hang*lie)==len(str1))):
break
else:
if (hang*lie)==len(str):
print("要变化的数码问题错误,返回至输入项——>>>")
elif ((hang*lie)==len(str1)):
print("输入的变化后的数码错误,返回至输入项——>>>")
else:
print("数码的格式错误,返回至输入项——>>>")
#print(str[0])
newnumber = change(str)
endnumber = change(str1)
end = dict()
for i in range(0,hang):
for j in range(0,lie):
end[endnumber[i][j]]=(i,j)
m=h(newnumber,endnumber)
n=g(newnumber,endnumber)
open=[]
maind = A(newnumber, endnumber)
while(True):
if(maind==True):
break
else:
for i in range(0,len(open)):
if (same(maind[0],open[i])):
maind[4]=hang*lie*10
if(same(maind[1],open[i])):
maind[5]=hang*lie*10
if(same(maind[2],open[i])):
maind[6]=hang*lie*10
if(same(maind[3],open[i])):
maind[7]=hang*lie*10
l1=maind[0]
l2=maind[1]
l3=maind[2]
l4=maind[3]
l1n=maind[4]
l2n=maind[5]
l3n=maind[6]
l4n=maind[7]
if (l1n <= l2n):
if (l3n <= l4n):
if (l1n <= l3n):
print(l1)
maind = A(l1, endnumber)
open.append(l1)
continue
else:
print(l3)
maind = A(l3, endnumber)
open.append(l3)
continue
else:
if (l1n <= l4n):
print(l1)
maind = A(l1, endnumber)
open.append(l1)
continue
else:
print(l4)
maind = A(l4, endnumber)
open.append(l4)
continue
else:
if (l3n <= l4n):
if (l2n <= l3n):
print(l2)
maind = A(l2, endnumber)
open.append(l2)
continue
else:
print(l3)
maind = A(l3, endnumber)
open.append(l3)
continue
else:
if (l2n <= l4n):
print(l2)
maind = A(l2, endnumber)
open.append(l2)
continue
else:
print(l4)
maind = A(l4, endnumber)
open.append(l4)
continue
实验结果:
以上方例子运行代码,结果如下:
输入要变化的数码问题的顺序(数据自左到右,自上到下):2831647 5
输入变化后的数码问题的顺序(数据自左到右,自上到下):1238 4765
输入数码的行数:3
输入数码的列数:3
[['2' '8' '3']
['1' ' ' '4']
['7' '6' '5']]
[['2' ' ' '3']
['1' '8' '4']
['7' '6' '5']]
[[' ' '2' '3']
['1' '8' '4']
['7' '6' '5']]
[['1' '2' '3']
[' ' '8' '4']
['7' '6' '5']]
[['1' '2' '3']
['8' ' ' '4']
['7' '6' '5']]
以上是关于A*算法求解N数码的主要内容,如果未能解决你的问题,请参考以下文章