a算法教程
Ⅰ 关于A*算法和3D算法
A*算法是一种启发式搜索的算法,公式表示为: f(n)=g(n)+h(n)g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n)是从n到目标节点最佳路径的估计代价。3D算法,没看懂你说什么意思
Ⅱ A*算法应用,大家给点介绍,做课程设计
维基网络有很多的,大陆访问不了,可以设置个香港代理。
SHA 家族
[编辑首段]维基网络,自由的网络全书
跳转到: 导航, 搜寻
安全散列演算法能计算出一个数位讯息所对应到的,长度固定的字串(又称讯息摘要)。且若输入的讯息不同,它们对应到不同字串的机率很高;而 SHA 是FIPS所认证的五种安全杂凑演算法。这些演算法之所以称作“安全”是基于以下两点(根据官方标准的描述):“1)由讯息摘要反推原输入讯息,从计算理论上来说是很困难的。2)想要找到两组不同的讯息对应到相同的讯息摘要,从计算理论上来说也是很困难的。任何对输入讯息的变动,都有很高的机率导致其产生的讯息摘要迥异。”
SHA 家族的五个演算法,分别是SHA-1, SHA-224, SHA-256, SHA-384, 和 SHA-512,由美国国家安全局 (NSA) 所设计,并由美国国家标准与技术研究院(NIST) 发布;是美国的政府标准。后四者有时并称为SHA-2。SHA-1 在许多安全协定中广为使用,包括 TLS 和 SSL、 PGP、SSH、S/MIME 和 IPsec,曾被视为是 MD5(更早之前被广为使用的杂凑函数)的后继者。但 SHA-1 的安全性如今被密码学家严重质疑;虽然至今尚未出现对 SHA-2 有效的攻击,它的演算法跟 SHA-1 基本上仍然相似;因此有些人开始发展其他替代的杂凑演算法。缘于最近对 SHA-1 的种种攻击发表,“美国国家标准与技术研究院(NIST)开始设法经由公开竞争管道(类似高级加密标准AES的发展经过),发展一个或多个新的杂凑演算法。”
目录 [隐藏]
1 SHA-0 和 SHA-1
1.1 SHA-0 的破解
1.2 SHA-1 的破解
2 SHA-2
3 SHA 所定义的长度
4 SHAd
5 应用
6 SHA-1 演算法
7 SHA-2 演算法
8 参见
9 参考资料
10 外部链结
[编辑] SHA-0 和 SHA-1
SHA-1 压缩演算法中的一个回圈。A, B, C, D 和 E 是这个state中的 32 位元文字;F 是会变化的非线性函数;<<<n 代表bit向左循环移动n个位置。n因操作而异。田代表molo 232之下的加法,Kt 是一个常数。最初载明的演算法于 1993年发布,称做安全杂凑标准 (Secure Hash Standard),FIPS PUB 180。这个版本现在常被称为 SHA-0。它在发布之后很快就被 NSA 撤回,并且由 1995年发布的修订版本 FIPS PUB 180-1 (通常称为 SHA-1) 取代。SHA-1 和 SHA-0 的演算法只在压缩函数的讯息转换部份差了一个位元的循环位移。根据 NSA 的说法,它修正了一个在原始演算法中会降低密码安全性的错误。然而 NSA 并没有提供任何进一步的解释或证明该错误已被修正。而后 SHA-0 和 SHA-1 的弱点相继被攻破,SHA-1 似乎是显得比 SHA-0 有抵抗性,这多少证实了 NSA 当初修正演算法以增进安全性的声明。
SHA-0 和 SHA-1 可将一个最大 264 位元的讯息,转换成一串 160 位元的讯息摘要;其设计原理相似于 MIT 教授 Ronald L. Rivest 所设计的密码学杂凑演算法 MD4 和 MD5。
[编辑] SHA-0 的破解
在 CRYPTO 98 上,两位法国研究者提出一种对 SHA-0 的攻击方式 (Chabaud and Joux, 1998): 在 261的计算复杂度之内,就可以发现一次碰撞(即两个不同的讯息对应到相同的讯息摘要);这个数字小于 280 ,也就是说,其安全性不到一个理想的杂凑函数抵抗攻击所应具备的计算复杂度。
2004年时,Biham 和 Chen 也发现了 SHA-0 的近似碰撞 — 两个讯息可以杂凑出几乎相同的数值;其中 162 位元中有 142 位元相同。他们也发现了 SHA-0 的完整碰撞(相对于近似碰撞),将本来需要 80 次方的复杂度降低到 62 次方。
2004年8月12日,Joux, Carribault, Lemuet 和 Jalby 宣布找到 SHA-0 演算法的完整碰撞的方法,这是归纳 Chabaud 和 Joux 的攻击所完成的结果。发现一个完整碰撞只需要 251的计算复杂度。他们使用的是一台有 256 颗 Itanium2 处理器的超级电脑,约耗 80,000 CPU 工时 [1]。
2004年8月17日,在 CRYPTO 2004 的 Rump 会议上,王小云, 冯登国 (Feng), 来学嘉 (Lai), 和于红波 (Yu) 宣布了攻击 MD5、SHA-0 和其他杂凑函数的初步结果。他们攻击 SHA-0 的计算复杂度是 240,这意谓的他们的攻击成果比 Joux 还有其他人所做的更好。请参见 MD5 安全性。2005 年二月,王小云和殷益群、于红波再度发表了对 SHA-0 破密的演算法,可在 239 的计算复杂度内就找到碰撞。
[编辑] SHA-1 的破解
鉴于 SHA-0 的破密成果,专家们建议那些计画利用 SHA-1 实作密码系统的人们也应重新考虑。2004 年 CRYPTO 会议结果公布之后,NIST 即宣布他们将逐渐减少使用 SHA-1,改以 SHA-2 取而代之。
2005年,Rijmen 和 Oswald 发表了对 SHA-1 较弱版本(53次的加密回圈而非80次)的攻击:在 280 的计算复杂度之内找到碰撞。
2005年二月,王小云、殷益群及于红波发表了对完整版 SHA-1 的攻击,只需少于 269 的计算复杂度,就能找到一组碰撞。(利用暴力搜寻法找到碰撞需要 280 的计算复杂度。)
这篇论文的作者们写道;“我们的破密分析是以对付 SHA-0 的差分攻击、近似碰撞、多区块碰撞技术、以及从 MD5 演算法中寻找碰撞的讯息更改技术为基础。没有这些强力的分析工具,SHA-1 就无法破解。”此外,作者还展示了一次对 58 次加密回圈 SHA-1 的破密,在 233 个单位操作内就找到一组碰撞。完整攻击方法的论文发表在 2005 年八月的 CRYPTO 会议中。
殷益群在一次面谈中如此陈述:“大致上来说,我们找到了两个弱点:其一是前置处理不够复杂;其二是前 20 个回圈中的某些数学运算会造成不可预期的安全性问题。”
2005 年八月 17 的 CRYPTO 会议尾声中王小云、姚期智、姚储枫再度发表更有效率的 SHA-1 攻击法,能在 263 个计算复杂度内找到碰撞。
在密码学的学术理论中,任何攻击方式,其计算复杂度若少于暴力搜寻法所需要的计算复杂度,就能被视为针对该密码系统的一种破密法;这并不表示该破密法已经可以进入实际应用的阶段。
就应用层面的考量而言,一种新的破密法出现,暗示着将来可能会出现更有效率、足以实用的改良版本。虽然这些实用的破密法版本根本还没诞生,但确有必要发展更强的杂凑演算法来取代旧的演算法。在“碰撞”攻击法之外,另有一种反译攻击法,就是由杂凑出的字串反推原本的讯息;反译攻击的严重性更在碰撞攻击之上。 在许多会应用到密码杂凑的情境(如用户密码的存放、文件的数位签章等)中,碰撞攻击的影响并不是很大。举例来说,一个攻击者可能不会只想要伪造一份一模一样的文件,而会想改造原来的文件,再附上合法的签章,来愚弄持有私密金钥的验证者。另一方面,如果可以从密文中反推未加密前的使用者密码,攻击者就能利用得到的密码登入其他使用者的帐户,而这种事在密码系统中是不能被允许的。但若存在反译攻击,只要能得到指定使用者密码杂凑过后的字串(通常存在影档中,而且可能不会透露原密码资讯),就有可能得到该使用者的密码。
2006 年的 CRYPTO 会议上,Christian Rechberger 和 Christophe De Cannière 宣布他们能在容许攻击者决定部分原讯息的条件之下,找到 SHA-1 的一个碰撞。
[编辑] SHA-2
SHA-2 的第t个加密回圈。图中的深蓝色方块是事先定义好的非线性函数。ABCDEFGH一开始分别是八个初始值,Kt是第t个金钥,Wt是本区块产生第t个word。原讯息被切成固定长度的区块,对每一个区块,产生n个word(n视演算法而定),透过重复运作回圈n次对ABCDEFGH这八个工作区段循环加密。最后一次回圈所产生的八段字串合起来即是此区块对应到的杂凑字串。若原讯息包含数个区块,则最后还要将这些区块产生的杂凑字串加以混合才能产生最后的杂凑字串。NIST 发布了三个额外的 SHA 变体,这三个函数都将讯息对应到更长的讯息摘要。以它们的摘要长度 (以位元计算) 加在原名后面来命名:SHA-256,SHA-384 和 SHA-512。它们发布于 2001年的 FIPS PUB 180-2 草稿中,随即通过审查和评论。包含 SHA-1 的 FIPS PUB 180-2,于 2002年以官方标准发布。2004年2月,发布了一次 FIPS PUB 180-2 的变更通知,加入了一个额外的变种 "SHA-224",这是为了符合双金钥 3DES 所需的金钥长度而定义。
SHA-256 和 SHA-512 是很新的杂凑函数,前者以定义一个word为32位元,后者则定义一个word为64位元。它们分别使用了不同的偏移量,或用不同的常数,然而,实际上二者结构是相同的,只在回圈执行的次数上有所差异。 SHA-224 以及 SHA-384 则是前述二种杂凑函数的截短版,利用不同的初始值做计算。
这些新的杂凑函数并没有接受像 SHA-1 一样的公众密码社群做详细的检验,所以它们的密码安全性还不被大家广泛的信任。Gilbert 和 Handschuh (2003) 曾对这些新变种作过一些研究,声称他们没有弱点。
[编辑] SHA 所定义的长度
下表中的中继杂凑值(internal state)表示对每个资料区块压缩杂凑过后的中继值(internal hash sum)。详情请参见Merkle-Damgård construction。
演算法 输出杂凑值长度 (bits) 中继杂凑值长度 (bits) 资料区块长度 (bits) 最大输入讯息长度 (bits) 一个Word长度 (bits) 回圈次数 使用到的运运算元 碰撞攻击
SHA-0 160 160 512 264 − 1 32 80 +,and,or,xor,rotl 是
SHA-1 160 160 512 264 − 1 32 80 +,and,or,xor,rotl 存在263 的攻击
SHA-256/224 256/224 256 512 264 − 1 32 64 +,and,or,xor,shr,rotr 尚未出现
SHA-512/384 512/384 512 1024 2128 − 1 64 80 +,and,or,xor,shr,rotr 尚未出现
[编辑] SHAd
SHAd 函数是一个简单的相同 SHA 函数的重述:
SHAd-256(m)=SHA-256(SHA-256(m))。它会克服有关延伸长度攻击的问题。
[编辑] 应用
SHA-1, SHA-224, SHA-256, SHA-384 和 SHA-512 都被需要安全杂凑演算法的美国联邦政府所应用,他们也使用其他的密码演算法和协定来保护敏感的未保密资料。FIPS PUB 180-1 也鼓励私人或商业组织使用 SHA-1 加密。Fritz-chip 将很可能使用 SHA-1 杂凑函数来实现个人电脑上的数位版权管理。
首先推动安全杂凑演算法出版的是已合并的数位签章标准。
SHA 杂凑函数已被做为 SHACAL 分组密码演算法的基础。
[编辑] SHA-1 演算法
以下是 SHA-1 演算法的虚拟码:
Note: All variables are unsigned 32 bits and wrap molo 232 when calculating
Initialize variables:
h0 := 0x67452301
h1 := 0xEFCDAB89
h2 := 0x98BADCFE
h3 := 0x10325476
h4 := 0xC3D2E1F0
Pre-processing:
append the bit '1' to the message
append k bits '0', where k is the minimum number >= 0 such that the resulting message
length (in bits) is congruent to 448 (mod 512)
append length of message (before pre-processing), in bits, as 64-bit big-endian integer
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15
Extend the sixteen 32-bit words into eighty 32-bit words:
for i from 16 to 79
w[i] := (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) leftrotate 1
Initialize hash value for this chunk:
a := h0
b := h1
c := h2
d := h3
e := h4
Main loop:
for i from 0 to 79
if 0 ≤ i ≤ 19 then
f := (b and c) or ((not b) and d)
k := 0x5A827999
else if 20 ≤ i ≤ 39
f := b xor c xor d
k := 0x6ED9EBA1
else if 40 ≤ i ≤ 59
f := (b and c) or (b and d) or (c and d)
k := 0x8F1BBCDC
else if 60 ≤ i ≤ 79
f := b xor c xor d
k := 0xCA62C1D6
temp := (a leftrotate 5) + f + e + k + w[i]
e := d
d := c
c := b leftrotate 30
b := a
a := temp
Add this chunk's hash to result so far:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
Proce the final hash value (big-endian):
digest = hash = h0 append h1 append h2 append h3 append h4
上述关于 f 运算式列于 FIPS PUB 180-1 中 , 以下替代运算式也许也能在主要回圈里计算 f :
(0 ≤ i ≤ 19): f := d xor (b and (c xor d)) (alternative)
(40 ≤ i ≤ 59): f := (b and c) or (d and (b or c)) (alternative 1)
(40 ≤ i ≤ 59): f := (b and c) or (d and (b xor c)) (alternative 2)
(40 ≤ i ≤ 59): f := (b and c) + (d and (b xor c)) (alternative 3)
[编辑] SHA-2 演算法
以下是SHA-256 演算法的虚拟码。注意,64个word w[16..63]中的位元比起 SHA-1 演算法,混合的程度大幅提升。
Note: All variables are unsigned 32 bits and wrap molo 232 when calculating
Initialize variables
(first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19):
h0 := 0x6a09e667
h1 := 0xbb67ae85
h2 := 0x3c6ef372
h3 := 0xa54ff53a
h4 := 0x510e527f
h5 := 0x9b05688c
h6 := 0x1f83d9ab
h7 := 0x5be0cd19
Initialize table of round constants
(first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311):
k[0..63] :=
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
Pre-processing:
append the bit '1' to the message
append k bits '0', where k is the minimum number >= 0 such that the resulting message
length (in bits) is congruent to 448 (mod 512)
append length of message (before pre-processing), in bits, as 64-bit big-endian integer
Process the message in successive 512-bit chunks:
break message into 512-bit chunks
for each chunk
break chunk into sixteen 32-bit big-endian words w[0..15]
Extend the sixteen 32-bit words into sixty-four 32-bit words:
for i from 16 to 63
s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
w[i] := w[i-16] + s0 + w[i-7] + s1
Initialize hash value for this chunk:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7
Main loop:
for i from 0 to 63
s0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
maj := (a and b) xor (a and c) xor (b and c)
t2 := s0 + maj
s1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
ch := (e and f) xor ((not e) and g)
t1 := h + s1 + ch + k[i] + w[i]
h := g
g := f
f := e
e := d + t1
d := c
c := b
b := a
a := t1 + t2
Add this chunk's hash to result so far:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
h4 := h4 + e
h5 := h5 + f
h6 := h6 + g
h7 := h7 + h
Proce the final hash value (big-endian):
digest = hash = h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7
其中 ch 函数及 maj 函数可利用前述 SHA-1 的优化方式改写。
SHA-224 和 SHA-256 基本上是相同的, 除了:
h0 到 h7 的初始值不同,以及
SHA-224 输出时截掉 h7 的函数值。
SHA-512 和 SHA-256 的结构相同,但:
SHA-512 所有的数字都是64位元,
SHA-512 执行80次加密回圈而非64次,
SHA-512 初始值和常数拉长成64位元,以及
二者位元的偏移量和循环位移量不同。
SHA-384 和 SHA-512 基本上是相同的,除了:
h0 到 h7 的初始值不同,以及
SHA-384 输出时截掉 h6 和 h7 的函数值。
Ⅲ A*算法的其它算法
启发式搜索其实有很多的算法
比如:局部择优搜索法、最好优先搜索法等等。当然A*也是。这些算法都使用了启发函数,但在具体的选取最佳搜索节点时的策略不同。像局部择优搜索法,就是在搜索的过程中选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,而一直得搜索下去。这种搜索的结果很明显,由于舍弃了其他的节点,可能也把最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不一定是全局的最佳。最好优先就聪明多了,他在搜索时,并没有舍弃节点(除非该节点是死节点),在每一步的估价中都把当前的节点和以前的节点的估价值比较得到一个“最佳的节点”。这样可以有效的防止“最佳节点”的丢失。那么A*算法又是一种什么样的算法呢?
Ⅳ 矩阵a*算法是什么
矩阵A*表示A矩阵的伴随矩阵。
伴随矩阵的定义:某矩阵A各元素的代数余子式,组成一个新的矩阵后再进行一下转置,叫做A的伴随矩阵。
某元素代数余子式就是去掉矩阵中某元素所在行和列元素后的形成矩阵的行列式,再乘上-1的(行数+列数)次方。
伴随矩阵的求发:当矩阵是大于等于二阶时:
主对角元素是将原矩阵该元素所在行列去掉再求行列式。
非主对角元素是原矩阵该元素的共轭位置的元素去掉所在行列求行列式乘以(-1)^(x+y) x,y为该元素的共轭位置的元素的行和列的序号,序号从1开始的。
主对角元素实际上是非主对角元素的特殊情况,因为x=y,所以(-1)^(x+y)=(-1)^(2x)=1,一直是正数,没必要考虑主对角元素的符号问题。
Ⅳ 用java怎么实现A*算法
代码实现(Java)
1.输入
(1)代表地图二值二维数组(0表示可通路,1表示路障)
int[][]maps={
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,0,0,0,0,0,0,1,1,1,0,0},
{0,0,0,1,0,0,0,0,0,1,1,0,0,0,0},
{0,0,0,1,0,0,0,0,1,1,0,0,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,0,0,0,0}
};123456789123456789
(2)按照二维数组的特点,坐标原点在左上角,所以y是高,x是宽,y向下递增,x向右递增,我们将x和y封装成一个类,好传参,重写equals方法比较坐标(x,y)是不是同一个。
publicclassCoord
{
publicintx;
publicinty;
publicCoord(intx,inty)
{
this.x=x;
this.y=y;
}
@Override
publicbooleanequals(Objectobj)
{
if(obj==null)returnfalse;
if(objinstanceofCoord)
{
Coordc=(Coord)obj;
returnx==c.x&&y==c.y;
}
returnfalse;
}
}2223
(3)封装路径结点类,字段包括:坐标、G值、F值、父结点,实现Comparable接口,方便优先队列排序。
<Node>
{
publicCoordcoord;//坐标
publicNodeparent;//父结点
publicintG;//G:是个准确的值,是起点到当前结点的代价
publicintH;//H:是个估值,当前结点到目的结点的估计代价
publicNode(intx,inty)
{
this.coord=newCoord(x,y);
}
publicNode(Coordcoord,Nodeparent,intg,inth)
{
this.coord=coord;
this.parent=parent;
G=g;
H=h;
}
@Override
publicintcompareTo(Nodeo)
{
if(o==null)return-1;
if(G+H>o.G+o.H)
return1;
elseif(G+H<o.G+o.H)return-1;
return0;
}
}
(4)最后一个数据结构是A星算法输入的所有数据,封装在一起,传参方便。:grin:
publicclassMapInfo
{
publicint[][]maps;//二维数组的地图
publicintwidth;//地图的宽
publicinthight;//地图的高
publicNodestart;//起始结点
publicNodeend;//最终结点
publicMapInfo(int[][]maps,intwidth,inthight,Nodestart,Nodeend)
{
this.maps=maps;
this.width=width;
this.hight=hight;
this.start=start;
this.end=end;
}
}
2.处理
(1)在算法里需要定义几个常量来确定:二维数组中哪个值表示障碍物、二维数组中绘制路径的代表值、计算G值需要的横纵移动代价和斜移动代价。
publicfinalstaticintBAR=1;//障碍值
publicfinalstaticintPATH=2;//路径
publicfinalstaticintDIRECT_VALUE=10;//横竖移动代价
publicfinalstaticintOBLIQUE_VALUE=14;//斜移动代价12341234
(2)定义两个辅助表:Open表和Close表。Open表的使用是需要取最小值,在这里我们使用Java工具包中的优先队列PriorityQueue,Close只是用来保存结点,没其他特殊用途,就用ArrayList。
Queue<Node>openList=newPriorityQueue<Node>();//优先队列(升序)
List<Node>closeList=newArrayList<Node>();1212
(3)定义几个布尔判断方法:最终结点的判断、结点能否加入open表的判断、结点是否在Close表中的判断。
/**
*判断结点是否是最终结点
*/
privatebooleanisEndNode(Coordend,Coordcoord)
{
returncoord!=null&&end.equals(coord);
}
/**
*判断结点能否放入Open列表
*/
(MapInfomapInfo,intx,inty)
{
//是否在地图中
if(x<0||x>=mapInfo.width||y<0||y>=mapInfo.hight)returnfalse;
//判断是否是不可通过的结点
if(mapInfo.maps[y][x]==BAR)returnfalse;
//判断结点是否存在close表
if(isCoordInClose(x,y))returnfalse;
returntrue;
}
/**
*判断坐标是否在close表中
*/
privatebooleanisCoordInClose(Coordcoord)
{
returncoord!=null&&isCoordInClose(coord.x,coord.y);
}
/**
*判断坐标是否在close表中
*/
privatebooleanisCoordInClose(intx,inty)
{
if(closeList.isEmpty())returnfalse;
for(Nodenode:closeList)
{
if(node.coord.x==x&&node.coord.y==y)
{
returntrue;
}
}
returnfalse;
}353637383940414243444546
(4)计算H值,“曼哈顿”法,坐标分别取差值相加
privateintcalcH(Coordend,Coordcoord)
{
returnMath.abs(end.x-coord.x)+Math.abs(end.y-coord.y);
}12341234
(5)从Open列表中查找结点
privateNodefindNodeInOpen(Coordcoord)
{
if(coord==null||openList.isEmpty())returnnull;
for(Nodenode:openList)
{
if(node.coord.equals(coord))
{
returnnode;
}
}
returnnull;
}
(6)添加邻结点到Open表
/**
*添加所有邻结点到open表
*/
(MapInfomapInfo,Nodecurrent)
{
intx=current.coord.x;
inty=current.coord.y;
//左
addNeighborNodeInOpen(mapInfo,current,x-1,y,DIRECT_VALUE);
//上
addNeighborNodeInOpen(mapInfo,current,x,y-1,DIRECT_VALUE);
//右
addNeighborNodeInOpen(mapInfo,current,x+1,y,DIRECT_VALUE);
//下
addNeighborNodeInOpen(mapInfo,current,x,y+1,DIRECT_VALUE);
//左上
addNeighborNodeInOpen(mapInfo,current,x-1,y-1,OBLIQUE_VALUE);
//右上
addNeighborNodeInOpen(mapInfo,current,x+1,y-1,OBLIQUE_VALUE);
//右下
addNeighborNodeInOpen(mapInfo,current,x+1,y+1,OBLIQUE_VALUE);
//左下
addNeighborNodeInOpen(mapInfo,current,x-1,y+1,OBLIQUE_VALUE);
}
/**
*添加一个邻结点到open表
*/
(MapInfomapInfo,Nodecurrent,intx,inty,intvalue)
{
if(canAddNodeToOpen(mapInfo,x,y))
{
Nodeend=mapInfo.end;
Coordcoord=newCoord(x,y);
intG=current.G+value;//计算邻结点的G值
Nodechild=findNodeInOpen(coord);
if(child==null)
{
intH=calcH(end.coord,coord);//计算H值
if(isEndNode(end.coord,coord))
{
child=end;
child.parent=current;
child.G=G;
child.H=H;
}
else
{
child=newNode(coord,current,G,H);
}
openList.add(child);
}
elseif(child.G>G)
{
child.G=G;
child.parent=current;
//重新调整堆
openList.add(child);
}
}
}85960618596061
(7)回溯法绘制路径
privatevoiddrawPath(int[][]maps,Nodeend)
{
if(end==null||maps==null)return;
System.out.println("总代价:"+end.G);
while(end!=null)
{
Coordc=end.coord;
maps[c.y][c.x]=PATH;
end=end.parent;
}
}12345678910111234567891011
(8)开始算法,循环移动结点寻找路径,设定循环结束条件,Open表为空或者最终结点在Close表
publicvoidstart(MapInfomapInfo)
{
if(mapInfo==null)return;
//clean
openList.clear();
closeList.clear();
//开始搜索
openList.add(mapInfo.start);
moveNodes(mapInfo);
}
/**
*移动当前结点
*/
privatevoidmoveNodes(MapInfomapInfo)
{
while(!openList.isEmpty())
{
if(isCoordInClose(mapInfo.end.coord))
{
drawPath(mapInfo.maps,mapInfo.end);
break;
}
Nodecurrent=openList.poll();
closeList.add(current);
addNeighborNodeInOpen(mapInfo,current);
}
}
Ⅵ A*算法的简单案例
参见参考资料中的“A*算法入门”
另外,A*同样可以用于其他搜索问题。
Ⅶ 我想了解一下五子棋AI A*算法,可是怎么都看不明白啊~谁能详细讲讲啊
/*源程序太多了,要的话给油箱*/
#DEFINE NROW 15
tmpzth="" && 行状态
tmpztl="" && 列状态
for i=1 to NROW
for j=1 to NROW
tmpzth=tmpzth+Azt(i,j)
tmpztl=tmpztl+Azt(j,i)
endfor
&& 行判断
do case
********** y 连 5 ***********
case "nyyyy" $ tmpzth
thisform.plc_h(i,j,at("nyyyy",tmpzth),0 ,1) && 1 的得出方法 :at("n","nyyyy")
case "ynyyy" $ tmpzth
thisform.plc_h(i,j,at("ynyyy",tmpzth),1 ,1)
case "yynyy" $ tmpzth
thisform.plc_h(i,j,at("yynyy",tmpzth),2 ,1)
case "yyyny" $ tmpzth
thisform.plc_h(i,j,at("yyyny",tmpzth),3 ,1)
case "yyyyn" $ tmpzth
thisform.plc_h(i,j,at("yyyyn",tmpzth),4 ,1)
********** b 连 5 **********
case "nbbbb" $ tmpzth
thisform.plc_h(i,j,at("nbbbb",tmpzth),0 ,2)
case "bnbbb" $ tmpzth
thisform.plc_h(i,j,at("bnbbb",tmpzth),1 ,2)
case "bbnbb" $ tmpzth
thisform.plc_h(i,j,at("bbnbb",tmpzth),2 ,2)
case "bbbnb" $ tmpzth
thisform.plc_h(i,j,at("bbbnb",tmpzth),3 ,2)
case "bbbbn" $ tmpzth
thisform.plc_h(i,j,at("bbbbn",tmpzth),4 ,2)
********** y 冲 4 ***********
case "nynyyn" $ tmpzth
thisform.plc_h(i,j,at("nynyyn",tmpzth),2 ,3)
case "nyynyn" $ tmpzth
thisform.plc_h(i,j,at("nyynyn",tmpzth),3 ,3)
case "nyyynn" $ tmpzth
thisform.plc_h(i,j,at("nyyynn",tmpzth),4 ,3)
case "nnyyyn" $ tmpzth
thisform.plc_h(i,j,at("nnyyyn",tmpzth),1 ,3)
********* b 冲 4 ************
case "nbnbbn" $ tmpzth
thisform.plc_h(i,j,at("nbnbbn",tmpzth),2 ,5)
case "nbbnbn" $ tmpzth
thisform.plc_h(i,j,at("nbbnbn",tmpzth),3 ,5)
case "nbbbnn" $ tmpzth
thisform.plc_h(i,j,at("nbbbnn",tmpzth),4 ,5)
case "nnbbbn" $ tmpzth
thisform.plc_h(i,j,at("nnbbbn",tmpzth),1 ,5)
********** y 连 4 ***********
case "nnyyyb" $ tmpzth
thisform.plc_h(i,j,at("nnyyyb",tmpzth),1 ,4)
case "nynyyb" $ tmpzth
thisform.plc_h(i,j,at("nynyyb",tmpzth),2 ,4)
case "nyynyb" $ tmpzth
thisform.plc_h(i,j,at("nyynyb",tmpzth),3 ,4)
case "nyyynb" $ tmpzth
thisform.plc_h(i,j,at("nyyynb",tmpzth),1 ,4)
case "byyynn" $ tmpzth
thisform.plc_h(i,j,at("byyynn",tmpzth),4 ,4)
case "byynyn" $ tmpzth
thisform.plc_h(i,j,at("byynyn",tmpzth),3 ,4)
case "bynyyn" $ tmpzth
thisform.plc_h(i,j,at("bynyyn",tmpzth),2 ,4)
case "bnyyyn" $ tmpzth
thisform.plc_h(i,j,at("bnyyyn",tmpzth),1 ,4)
********** b 连 4 ***********
case "nnbbby" $ tmpzth
thisform.plc_h(i,j,at("nnbbby",tmpzth),1 ,9)
case "nbnbby" $ tmpzth
thisform.plc_h(i,j,at("nbnbby",tmpzth),2 ,9)
case "nbbnby" $ tmpzth
thisform.plc_h(i,j,at("nbbnby",tmpzth),3 ,9)
case "nbbbny" $ tmpzth
thisform.plc_h(i,j,at("nbbbny",tmpzth),1 ,9)
case "ybbbnn" $ tmpzth
thisform.plc_h(i,j,at("ybbbnn",tmpzth),4 ,9)
case "ybbnbn" $ tmpzth
thisform.plc_h(i,j,at("ybbnbn",tmpzth),3 ,9)
case "ybnbbn" $ tmpzth
thisform.plc_h(i,j,at("ybnbbn",tmpzth),2 ,9)
case "ynbbbn" $ tmpzth
thisform.plc_h(i,j,at("ynbbbn",tmpzth),1 ,9)
********** y 冲 3 ***********
case "nynynn" $ tmpzth
thisform.plc_h(i,j,at("nynynn",tmpzth),2 ,6)
case "nnyynn" $ tmpzth
thisform.plc_h(i,j,at("nnyynn",tmpzth),4 ,6)
********* b 冲 3 ************
case "nbnbnn" $ tmpzth
thisform.plc_h(i,j,at("nbnbnn",tmpzth),2 ,8)
case "nnbbnn" $ tmpzth
thisform.plc_h(i,j,at("nnbbnn",tmpzth),4 ,8)
********** 1个 ***********
case "nnynnn" $ tmpzth
thisform.plc_h(i,j,at("nnynnn",tmpzth),3, 7)
case "nnnynn" $ tmpzth
thisform.plc_h(i,j,at("nnnynn",tmpzth),2 ,7)
case "nnbnnn" $ tmpzth
thisform.plc_h(i,j,at("nnbnnn",tmpzth),3 ,10)
case "nnnbnn" $ tmpzth
thisform.plc_h(i,j,at("nnnbnn",tmpzth),2 ,10)
endcase
&& 列判断
do case
********** 5个 ***********
case "nyyyy" $ tmpztl
thisform.plc_l(i,j,at("nyyyy",tmpztl),0 ,1) && 1 的得出方法 :at("n","nyyyy")
case "ynyyy" $ tmpztl
thisform.plc_l(i,j,at("ynyyy",tmpztl),1 ,1)
case "yynyy" $ tmpztl
thisform.plc_l(i,j,at("yynyy",tmpztl),2 ,1)
case "yyyny" $ tmpztl
thisform.plc_l(i,j,at("yyyny",tmpztl),3 ,1)
case "yyyyn" $ tmpztl
thisform.plc_l(i,j,at("yyyyn",tmpztl),4 ,1)
case "nbbbb" $ tmpztl
thisform.plc_l(i,j,at("nbbbb",tmpztl),0 ,2)
case "bnbbb" $ tmpztl
thisform.plc_l(i,j,at("bnbbb",tmpztl),1 ,2)
case "bbnbb" $ tmpztl
thisform.plc_l(i,j,at("bbnbb",tmpztl),2 ,2)
case "bbbnb" $ tmpztl
thisform.plc_l(i,j,at("bbbnb",tmpztl),3 ,2)
case "bbbbn" $ tmpztl
thisform.plc_l(i,j,at("bbbbn",tmpztl),4 ,2)
********** 4个 ***********
case "nynyyn" $ tmpztl
thisform.plc_l(i,j,at("nynyyn",tmpztl),2 ,3)
case "nyynyn" $ tmpztl
thisform.plc_l(i,j,at("nyynyn",tmpztl),3 ,3)
case "nyyynn" $ tmpztl
thisform.plc_l(i,j,at("nyyynn",tmpztl),4 ,3)
case "nnyyyn" $ tmpztl
thisform.plc_l(i,j,at("nnyyyn",tmpztl),1 ,3)
case "nbnbbn" $ tmpztl
thisform.plc_l(i,j,at("nbnbbn",tmpztl),2 ,5)
case "nbbnbn" $ tmpztl
thisform.plc_l(i,j,at("nbbnbn",tmpztl),3 ,5)
case "nbbbnn" $ tmpztl
thisform.plc_l(i,j,at("nbbbnn",tmpztl),4 ,5)
case "nnbbbn" $ tmpztl
thisform.plc_l(i,j,at("nnbbbn",tmpztl),1 ,5)
********** 3个 ***********
case "nnyyyb" $ tmpztl
thisform.plc_l(i,j,at("nnyyyb",tmpztl),1 ,4)
case "nynyyb" $ tmpztl
thisform.plc_l(i,j,at("nynyyb",tmpztl),2 ,4)
case "nyynyb" $ tmpztl
thisform.plc_l(i,j,at("nyynyb",tmpztl),3 ,4)
case "nyyynb" $ tmpztl
thisform.plc_l(i,j,at("nyyynb",tmpztl),1 ,4)
case "byyynn" $ tmpztl
thisform.plc_l(i,j,at("byyynn",tmpztl),4 ,4)
case "byynyn" $ tmpztl
thisform.plc_l(i,j,at("byynyn",tmpztl),3 ,4)
case "bynyyn" $ tmpztl
thisform.plc_l(i,j,at("bynyyn",tmpztl),2 ,4)
case "bnyyyn" $ tmpztl
thisform.plc_l(i,j,at("bnyyyn",tmpztl),1 ,4)
case "nnbbby" $ tmpztl
thisform.plc_l(i,j,at("nnbbby",tmpztl),1 ,9)
case "nbnbby" $ tmpztl
thisform.plc_l(i,j,at("nbnbby",tmpztl),2 ,9)
case "nbbnby" $ tmpztl
thisform.plc_l(i,j,at("nbbnby",tmpztl),3 ,9)
case "nbbbny" $ tmpztl
thisform.plc_l(i,j,at("nbbbny",tmpztl),1 ,9)
case "ybbbnn" $ tmpztl
thisform.plc_l(i,j,at("ybbbnn",tmpztl),4 ,9)
case "ybbnbn" $ tmpztl
thisform.plc_l(i,j,at("ybbnbn",tmpztl),3 ,9)
case "ybnbbn" $ tmpztl
thisform.plc_l(i,j,at("ybnbbn",tmpztl),2 ,9)
case "ynbbbn" $ tmpztl
thisform.plc_l(i,j,at("ynbbbn",tmpztl),1 ,9)
********** 2个 ***********
case "nynynn" $ tmpztl
thisform.plc_l(i,j,at("nynynn",tmpztl),2 ,6)
case "nnyynn" $ tmpztl
thisform.plc_l(i,j,at( "nnyynn",tmpztl),4 ,6)
case "nbnbnn" $ tmpztl
thisform.plc_l(i,j,at("nbnbnn",tmpztl),2 ,8)
case "nnbbnn" $ tmpztl
thisform.plc_l(i,j,at("nnbbnn",tmpztl),4 ,8)
********** 1个 ***********
case "nnynnn" $ tmpztl
thisform.plc_l(i,j,at("nnynnn",tmpztl),3, 7)
case "nnnynn" $ tmpztl
thisform.plc_l(i,j,at("nnnynn",tmpztl),2 ,7)
case "nnbnnn" $ tmpztl
thisform.plc_l(i,j,at("nnbnnn",tmpztl),3 ,10)
case "nnnbnn" $ tmpztl
thisform.plc_l(i,j,at("nnnbnn",tmpztl),2 ,10)
endcase
tmpzth=""
tmpztl=""
endfor
Ⅷ 什么是 a算法a* 算法有什么特点
A*算法:A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法。估价值与实际值越接近,估价函数取得就越好
A* (A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。
注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为: f(n)=g(n)+h(n),
其中 f(n) 是从初始点经由节点n到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。