华容道搜索算法研究

转载地址已经废弃,这里做个备份。

作者: 许剑伟 2006五一节于福建莆田十中

转载:http://www.fjptsz.com/xxjs/xjw/rj/110.htm
一、算法的由来:
也不知写了多少行程序,累了,写点轻松的吧,可千万不要和操作系统打交了!还有那该死的Socket,真讨厌,什么“缓冲区不足”,我不是有2G内存,怎么就不足了?
志雄正潜心研究24点算法,向我要全排列的算法,我给他一个利用堆栈解决方法,寥寥几行,志雄叫好。看他挺专心的,于是我也加入他的24点项目。花了一个晚上考虑算法,第二天早上,完全实现了我的算法,用时0.75秒,解出1900道24点题目的完全解,比较满意。第二天再和李雄讨论算法并最后定稿。后来李志雄和我谈起华容道的问题。想来颇为感慨,大概6年前,林清霞老师给我“华容道”时,我花费了整整一个下午时间,也没能走出来,一恼火,打开电脑编程来解。用TC2.0编写一个程序,花了一天,终于写好,并得到结果。可如今再提“华容道”时,我竟然对当时的算法很模糊,我知道写那种程序有一定难度,可多年后,在我更加熟悉程序设计之后,怎么突然没头绪了,只记得当时写象棋程序花费了不少时间,华容道应是小问题,当时的我到底有用了什么招术?我想,我应再闯“华容道”。
可是要用什么算法呢?在网络上找了很久,看了几篇,没找到我满意的,仔细分析,这些算法效率不行,我不想采用。于是我又坐下来考虑算法,3个小时过去了,终于有眉目了。
本文算法可在40毫秒内解出“横刀立马”(P2.4G),其它棋局耗时略有不同。本文程序利用哈希技术优化后速度提高3倍,约12ms/题。
二、棋局:
横刀立马
华容道搜索算法研究_第1张图片

图中棋子共10个,滑动棋子,把曹操移正下方出口。
有数学家指出,此问题单靠数学方法很难求解。
“华容道”开局布阵有数百种,以上仅是一种。
三、前人研究:
引网文:“华容道”是世界著名的智力游戏。在国外和魔方、独粒钻石并列,被誉为”智力游戏界三大不可思议”并被编入学校的教科书。日本藤村幸三朗曾在《数理科学》杂志上发表华容道基本布局的最少步法为85步。后来清水达雄找出更少的步法为83步。美国著名数学家马丁·加德纳又进一步把它减少为81步。此后,至今还未曾见到打破这一记录的报道。

网络上可找到几个有效的算法例程,一个是PASCAL的,一个是VB的,一个是C的,还有一个针对手机的java源代码,都指明使用广度优先算法及一些剪枝办法。但算法效率仍然不高。天津师范大李学武《华容道游戏的搜索策略》说到使用双向搜索可提高效率,但本文未采用这种方法,我觉得目标结点不好选择。有篇文章说对称的节点可以不搜索,想了想确实有道理,本文采用了。后来又在网络上找到几个华容道游戏程序,其中李智广的程序效率较高(V2.0) ,本想细仔研究它,可是很遗憾,未能找到它的算法说明,只好自已动手设计算法,经过2天努力,本文的搜索效率已远远超过它,足以证实算法的有效性。
四、算法:
(一)、广度优先搜索:这里简单介绍,不明白的话自己查查图、树相关资料吧。
一个盘面状态理解为一个节点,在编程时表示节点的方法是多样的,可用一串数字来表示盘面状态节点,通过压缩处理,甚至可用一个int32整型数来表示一个节点。
首先考查起始盘面(节点)的所有走法,然后逐一试走,设当前有n1种走法,则生成n1个儿子节点。
接下来,考查这n1个儿子节点的所有走法,并分别试走,生成n2个孙子节点。
接下来,考查这n2个孙子节点的所有走法,并分别试走,生成n3个曾孙节点。
再接下,就不多说了,依上循环,一代一代的往下生成节点,直到找到目标节点。
以上搜索思想朴素、简单,这也正是程序设计所需要的!可是摆在我们面前的问题有两个: a、代代生成子节点,将会有很多个节点,如何存取这些节点呢,也就是说如何有序的排放节点而不至于造成混乱。b、程序大概结构应是怎样的。

第1个问题可这样解决:设第一代节点放在A[1]中,第二代节点放在A[2]中,第三代节点放在A[3]……注意A[1]中含有多个节点,A[2]也是这样的……。
第2个问题可用以下伪代码解决:
//———————
展开首节点得所有儿子节点A[1]
for( i=1;i<=n层;I++){ //查找n代(层)
P1=A[i],P2=A[i+1]
for(j=1;j<=P1内节点个数;j++){
B=P1[j] //读取P中的第j个节点
检查B是否为目标节点,如果是,结束搜索
展开B并将所有节点追加到P2中 //P2为P1下一代的节点集
}
}
//———————
以上代码基本上给出了搜索算法,这种搜索本质上是广度优先算法。接下个我们来优化这个程序。
把第一代儿子节点放在A[1]中,那么A[1]要有多大空间来放节点所,显然第一代只需能放10个节点就够了,因为最多可能的走步不会超过10步,那第二代呢,肯定就多了,第三代还会更多……,每代所需空间都不一样,那我们要如何分配空间,如果使用javascript、PHP等脚本语言来编程,内存空间分配问题基本不用管,但用C语言呢。假如每代最多10000个节点,然后,您想搜索200代,为了简化程序,您可以简单的分配一个200*10000即可解决问题。现在电脑内存很多,用这些空间虽不算奢侈,并且会取得很高的搜索速度,但本着求精、节约的精神,有必要优化A[][]数组问题。基本思想方法就是将这个二维数组压入一个一维数组中去。这个特殊的一维数据,称为队。队和数组还有些区别,构成一个队一般还需要队头指针和队尾指针,当我们读写节点数据时,高度有序的移动这两个指针进行存取节点而不至于混乱。
伪程序中看到,第一代n1个儿子节点放在A[1]中,第二代放在A[2]中,这时A[1]中的很多空间就浪费了,不妨这样吧,读第一代节点时,把生成的第二代节点数据接在A[1]中最后一个节点之后,当第一代读完时,下一个就是第二代了;读第二代时,生成第三代节点,同样第三代也接往A[1]里的最后一节点之后,读的过程称出队,写过程过程称为入队。我们统一从队头开始读(出队),队尾处开始写(入队)。由于搜索时是一代代有序往下搜索,则队里的节点也是一代一代的往下接。
为了有序进行,读取儿子节点时,我们将队头指针指向儿子节点开始处,然后读取节点,读完后队头指针往后移动一步,当移动n1次后,就读完n1个儿子节点。在读儿子节点的过程中,我们同时试走儿子节点,生成孙子节点并入队。如此过程,在队头指针读完儿子节点后,队头指针就会指向第一个孙子节点上。伪代码如下一步
//———————
展开首节点A得所有儿子节点D数组(队)中
P=1,P2=最后一个; //P指向D的第一个(队头指针),P2指向D的最后一个(队尾指针)
for(i=1;i<=n层;I++){ //查找n代(层)
k=P2-P //当前层节点个数
for(j=1;j<=k;j++){
B=D[P] //读取D中的第P个节点
检查B是否为目标节点,如果是,结束搜索
展开B并将所有节点追加到D[P2]中
P++,P2+=B展开的个数
}
}
//———————

剪枝问题:
第n层(代)的某一节点M,往前试走一步生成Q,当然Q就是n+1层节点。Q有没有可能同以前走过的节点相同呢,当然有可能,走象棋时很明显,不同走法可能产生相同结果!设以前的走过节点都没有重复,Q不可能与小于n-1层的节点重复,如果重复会有什么会结果?Q到M只一步,M到Q也只需一步,Q与n-2层重复,则Q为n-2层而不是n+1层,Q可生成M,M就会在n-2+1=n-1层出现过,这时n和n-1层都有M,与题设矛盾。因此,每走一步,一直往前查到n-1层,如果Q没有重复即为新生节点,否则应剪枝(即这样的节点不能入队)。刚才说“往前查”,即使只限定在n-1层之后一个一个查,肯定还是慢,怎么办能,干脆每生成一个节点,就对这个节点建立索引,以后哪怕节点有万亿个也不怕。如何建索引表,下文再叙。
再细想,单是以上算法还是不够快。如:父亲A在移动曹操时,生了儿子P。儿子P生孙子时也移动曹操得到R,从棋局中发现这时R和A是同一节点,即父亲A等于孙子P,这是明显的节点重复,为这样的R去检查重复也是浪费时间。因此,发现要移动的棋子与父节点当时移动的子是同一个棋子就别试走,事实证明这样可少测试节点达1/3,使遍历速度提高20%。华容道棋局与象棋棋局不同,连续走两步移动同一个子,那么第二步是多余的,如果你要追求数学上的证明就自己动手证明吧。
我们还可进一步优化,某一盘面A1必存在与之左右对称的的盘面A2,目标节点M1必存在与之左右对称的盘面节点M2,设两节点最短路径为min(点1,点2),则min(A1,M1)==min(A2,M2),当M1为目标结点并且M2也为目标节点时,搜索A1和搜A2得到的最优结果是等价的,只需搜结果A1。华容道只要求曹操从正下方移出,所以M1,M2都是目标节点,因此,搜索了A1就没必要搜索其对称节点A2,这样可使程序效率提高近一倍。
通过以上剪枝优化,生成的树已接近最小树。
回朔问题:
当我写完程序时,发现把曹操移出后,却不知道是具体的移动过程,也就是说不知道具体的路径。原因在哪里呢?伪代码中没有记录走过的路径,当找到目标节点却不知道是如何走来的,因此产生儿子节点的过程中还应告诉儿子:它的父亲是谁。当我们得到目标结点后,我们就问目标结点:你的父亲是谁,然后我们找其父,再问:你的父亲是谁,如此一层一层往上追问,最后就知道了全路径。这个过程我常称“回溯”(也许不准确)。
(二)上文提到索引,如何索引。要解决索引问题,可能有很多种方法,首先想到的是使用哈希表的办法,哈希表是棋类游戏常用的方法,算法原理不难,不过实现起来也挺麻烦的,使用哈希表时一般使用随机数来建立索引,因此一定要选择有足够散列度随机数(或准随机算法),以免造成大量哈希冲突而降底效率。以下介绍的方法是通过编码及查表方法来完成节点索引,建立一种不会发生重复的索引。总之,就是要建立一个索引,哈希表是个有重复的索引(碰到冲突的一般要做二次哈希),编码方法是建立一个无重复索引。本文讲述的的编码方法得到的速度不会很快,如果你追求速度,最好使用哈希表建立索引,并且在计算哈希值时采用增量技术,这样计算索引号的速度可提高10至20倍,程序在10ms内可搜索出最优解。
盘面的状态(节点)数量是十分有限的,状态总数不会超过50万种。(横刀立马为例)
曹操的走法只有12种,任你如何排放,只有12种,不是20种。
横将(关羽)的排法最多只有11种
接下来对4个竖将排列(组合),排列第一个竖将的排法最多10种,第二个8种,第三个6种,第四个4种。组合数是10*8*6*4/4!=80,后来为来编程方便,做了更多冗于,组合数用C10取4,即C(10,4)=10*9*8*7/4!=210,这样,4个竖将的某一排列组合必对应0—209中的一个数,这个数就是我们所要的竖将组合编码值。
同理小兵的组合为C(6,4)=15,编码范围在0—14
因此对这4种(10个)棋子全排列,种数最多为12*11*210*15=415800,即4百多K。
最后易得盘面编码:各种棋子的编码值乘以码权,然后取和。
码权只需遵照排列规律,随你定,是比较简单的。可设兵的码权为1,竖将则是15,横将则为15*210,曹操为15*210*11。
要如何对各种棋子高速有效的编码呢?如“横刀立马”开局,如何编码?
这又变成一个组合问题。
我们一个一个的排放“横刀立马”棋子并演示编码过程。
曹操有12个可排放位置,这12个位置编号为0-11,曹操位置在1,注意,首个是0。
关羽有11个可排放位置,这11个位置编号为0-10,关羽位置在1个。
竖将有10个可排放的位置,编号为0-9,一将是0,二将是1,三将是4,四将是5。
小兵有6个可排放的位置,编号为0-5,一兵是0,二兵是1,三兵是2,四兵是5。
竖将编号序列为0,1,4,5,这一组合对应的组合序号(编码)是多少呢,如何定义?真还有点不好处理,有人说这与群论有关。我不太清楚,我就用了一些笨办法解决问题。0,1,4,5表示的是各个将的位置,竖将在位用1表示,不在位用0表示,则0,1,4,5可示意为11001100000,这不就成了二进制数,不妨把0145转为二进数,用查表法转换是很快的,只需4个加法语名即可完成,再用这个二进数当作数组的下标来查组合的编号表,从表中得到它的编号,设表为Sb,则编号值为Sb[11001100000]或Sb[816],这样就完成了高速编码。这个编号表如何建立呢?这也好办,事前把0000000000—1111111111共1024个数中含4个1的数按顺序编号,其中只有C(10,4)=210个数被编号,其余不用。由此建立一个1024长的有序表Sb[],表中位置下标含4个1的被编号,共210个。
竖将编码过程表示为:0145=>1100110000=>Sb[100110000]即Sb[816]
小兵同样方式编码0125=>111001=>Bb[111001]即Bb[57]

上述,编码后盘面总数最多为415800,当我们记录每一个节点是否已经遍历时,最多只需415800个字节,如果是广度搜索,还可按比特方法压缩8倍,只需415800/8=51975个字节,现在的计算机,内存很存都很强,随便一个new,就可得几兆内存,几百兆也没问题,哪里在乎这4百多K,跟本无需压缩,压缩也是在浪费时间。
有了上述排列组合的关系,便可很轻松的写一个编码函数,从而建立与节点相关的表或索引表等。如,可用编号做为数组的下标来询址,找到相应的节点记录。这样速度就会很快,在检查节点是否已经遍历过的时候,无需一个一个的往前查!速度要快几十倍!用广度搜索时,每层一般有数百个甚至上千个节点,一个一个的查过去是很费时的,如果再用解释型语言这么查,解一题,给2分钟也未必有结果!
编码也很费时,完成一个节点编码需可能需200个指令。一个一个查节点,比对二节点是否相同就不费时吗?也挺费时的,比对二个节点是否相同,要查遍4*5个方格,至少需要60条指令(优化后也需10),遍历检验重复节点时平均要查2.5层,每层平均有200个节点,设平均查了半数就可知道是否重复,因此判断一个节是否重复需要10*200*2.5/2+500(循环产生的)=7000多个指令。有人说对节点压缩可提速,其实不见得,因为压缩是需要时间的,别干吃力不讨好的事。当在DOS下编程,只能用640K内存时经常考虑压缩。总之编码比较费时。不编码则更费时,相差6000/200=30倍。
如上说,编码很费时,所以这200条指令应避免乘除指令,如何避免呢?尽量用查表法!如:要多次使用2的n次方,千万不要每次n个2相乘,应该在程序前端充分考虑运行过程中可能使用到的2的各种次方,先用乘法都算出来并列表(一般用数组),在需要多次使用时(如循环中语句中使用时),只需查表即可。
有了编码函数,也可用来对棋盘压缩。“横刀立马”最大编号为415800,只占用24bit(3个字节)。压缩棋盘后,就还要有个解压缩,用的当然是相应的解码算法。在DOS模式下,内存不够用多考虑压缩,用VC就没必要压缩了。
五、下一步工作:
通过以上算法,可得知几十步乃至百步以后演变的棋局,因此华容道问题已解决。下一步该考虑象棋的算法了。几年前写的程序没有打败自己,也有必要重写。打算使用深度优先算法,做更有效的剪枝和盘面估值。考虑加入开局库和残局库。

六、利用编码技术搜索华容道源代码:
文中代码使用C++编写,定义了一些类,使用纯C编写难度可能会更大一些,因为程序实现过程中使用了很多变量,不封装为类,变量使用会比较乱。
文中棋盘被定义为一个长度为20的一维字符型数组,定义为一维数组的有一定的好处,内层的循环可完全避免产生乘法指令。而且数组使用也更简单。
以下代码可再做优化,如使用内联函数等,由于内联函数中不能使用循环,写出来的程序会比较难看,所以未给出。做仔细优化,速度还可提高近一倍。
几个核心代码也可用汇编程序优化,按笔者经验,速度还可提高至少一倍,但程序会变得不知所云,我觉得并不可取。
程序支持的棋盘类型:含一个曹操,横将及竖将个数之和为5个,兵为4个

//---------------------------------------------------------------------------
//----本程序在C++Builder6.0及VC++6.0中调试通过----
//----程序名称:"华容道"搜索----
//----程序设计:许剑伟----
//----最后修改时间:2006.5.3----
//----速度:横刀立马40多毫秒(P2.4G机器)
//----如果优化走法生成器,速度为35毫秒,由于速度瓶胫在编码器上,所以为了让程序可读性好些不做优化
//----要彻底提高速度,请查阅下文中利用哈希技术的华容道算
//---------------------------------------------------------------------------
#include 
#include 
//---------------------------------------------------------------------------
//--以下定义一些常数或参数--
//---------------------------------------------------------------------------
//棋盘表示使用char一维数组,例:char q[20];
//1-15表示各棋子,空位用0表示,兵1-4,竖将5-9,横将10-14,大王15
//大王只能1个,将必须5个(横竖合计),兵必须为4个
const char U[]="ABBBBCCCCCHHHHHM";; //棋子类型表
const COL[20]={0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3};   //列号表
const ROW[20]={0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4};   //行号表
const WQ2[13]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096}; //二进制位权表(12个)
//---------------------------------------------------------------------------
//--以下定义几函数--
//---------------------------------------------------------------------------
//以下define用于棋盘复制,不要用环循,实地址直接引用要快8#define qpcpy(q1,q2) {/*复制棋盘*/\
  int *ls1=(int*)q1,*ls2=(int*)q2;\
  ls1[0]=ls2[0],ls1[1]=ls2[1],ls1[2]=ls2[2],ls1[3]=ls2[3],ls1[4]=ls2[4];\
}
//memset(JD,0,Bm.bmtot);
void qkmem(void *ps,int n){ //内存块置0
  register int *p=(int*)ps,*p2=p+n/4;
  while(p*p++=0;
  char *p3=(char *)p,*p4=(char *)ps+n;
  while(p3*p3++=0;
}
void prt(char *q){ //打印棋盘
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++) printf("%2d ",q[i*4+j]);
    printf("\r\n");
  }
  printf("\r\n");
}
//---------------------------------------------------------------------------
//--以下是搜索算法之一(解决编码问题)--
//---------------------------------------------------------------------------
class PmBm{ //盘面编码类
 public:
 short int *Hz,*Sz,*Bz;  //竖将,横将,小兵,组合序号表
 int *Hw,*Sw,Mw[12]; //权值表:横条,竖条,大王
 int bmtot;
 PmBm(char *q){//初始化编码表
   Hz=new short int[4096*3]; Sz=Hz+4096; Bz=Hz+4096*2;
   Hw =new int[792*2];  Sw=Hw+792;  //C12取5=792
   int i,j,k;
   int Hn=0,Bn=0,Sn=0; //各类子数目,大王默认为1不用计数
   for(i=0;i<20;i++){   //计算各种棋子的个数
     if(U[q[i]]=='B') Bn++;
     if(U[q[i]]=='H') Hn++;
     if(U[q[i]]=='C') Sn++;
   }
   Hn/=2,Sn/=2;
   int Hmax=WQ2[11],Smax=WQ2[12-Hn*2],Bmax=WQ2[16-(Hn+Sn)*2]; //各种子的最大二进位数
   int Hx=0,Sx=0,Bx=0; //各种棋子组合的最大序号
   for(i=0;i<4096;i++){  //初始化组合序号表
     for(j=0,k=0;j<12;j++) if(i&WQ2[j]) k++; //计算1的个数
     if(k==Hn&&iif(k==Sn&&iif(k==Bn&&iint Sq=Bx,Hq=Bx*Sx,Mq=Bx*Sx*Hx; //竖将位权,横将位权,王位权
   for(i=0;i<12;i++) Mw[i]=i*Mq; //初始化大王权值表
   for(i=0;i*Hq; //初始化横将权值表
   for(i=0;i*Sq; //初始化竖将权值表
   bmtot=Mq*12;
 }
 ~PmBm(){ delete[] Hz,Hw; }
 int BM(char *q){ //盘面编码
   int Bb=0,Bd=-1; //空位序号记录器
   int Sb=0,Sd=-1; //竖条序号记录器
   int Hb=0,Hd=-1; //横条序号记录器
   int Mb;         //大王序号记录器
   char c,lx,f[16]={0};   //其中f[]标记几个棋子是否已确定位置序号
   int i;
   for(i=0;i<20;i++){
     c=q[i],lx=U[c]; //当前的值
     if(lx=='M') { //大王定序
       if(!f[c]) Mb=i-ROW[i],f[c]=1;
       continue;
     }
     if(COL[i]<3&&U[q[i+1]]<='H') Hd++; //横条位置序号(编号)
     if(lx=='H') {//横将定序,转为二进制进行询址得Hb
       if(!f[c]) Hb+=WQ2[Hd],f[c]=1;
       continue;
     }
     if(ROW[i]<4&&U[q[i+4]]<='C') Sd++; //竖将位置序号(编号)
     if(lx=='C') { //竖条定序,转为二进制进行询址得Sb
       if(!f[c]) Sb+=WQ2[Sd],f[c]=1;
       continue;
     }
     if(lx<='B') Bd++;  //小兵位置序号(编号)
     if(lx=='B') Bb+=WQ2[Bd]; //小兵定序,转为二进制进行询址得Bb
   }
   //Hb,Sb,Bb为组合序号,"横刀立马"最大值为小兵C(6,4)-1=15-1,竖条C(10,4)-1=210-1
   Bb=Bz[Bb],Sb=Sz[Sb],Hb=Hz[Hb];//询址后得得Bb,Sb,Hb组合序号
   return Bb+Sw[Sb]+Hw[Hb]+Mw[Mb]; //用位权编码,其中Bb的位权为1
 }
 int dcBM(char *q){ //按左右对称规则考查棋盘,对其编码
   char i,q2[20];
   for(i=0;i<20;i+=4) q2[i]=q[i+3],q2[i+1]=q[i+2],q2[i+2]=q[i+1],q2[i+3]=q[i];
   return BM(q2);
 }
};
//---------------------------------------------------------------------------
//以下定义搜索过程使用的核心数据结构
//---------------------------------------------------------------------------
struct PMZB{ //盘面走步集结构
  char s[10],d[10];//原位置,目标位置,最多只会有10int n;           //总步数
};
//以下是走法生成器函数
#define kgpd(i)  (i==k1||i==k2) //空格判断宏
#define kgpd1(i) (i==k1&&h==1)  //竖联空格判断宏
#define kgpd2(i) (i==k1&&h==2)  //横联空格判断宏
#define zin(des) z->s[z->n]=i,z->d[z->n]=des,z->n++ //保存步法宏
void zbFX(char *q,PMZB *z){ //分析当前可能的步法,并将所有可能的步法保存在z中
  int i,col,k1=0,k2=0,h=0; //i,列,空格1位置,空格2位置,h为两空格的联合类型
  char c,lx,f[16]={0}; //f[]记录已判断过的棋字
  z->n=0; //计步复位

  for(i=0;i<20;i++){
    if(!q[i]) k1=k2,k2=i; //查空格的位置
  }
  if(k1+4==k2) h=1;            //空格竖联合
  if(k1+1==k2&&COL[k1]<3) h=2; //空格横联合
  for(i=0;i<20;i++){
    c=q[i],lx=U[c],col=COL[i];
    if(f[c]) continue;
    switch(lx){
     case 'M': //曹操可能的走步
       if(kgpd2(i+8))        zin(i+4);  //向下
       if(kgpd2(i-4))        zin(i-4);  //向上
       if(col<2&&kgpd1(i+2)) zin(i+1);  //向右
       if(col  &&kgpd1(i-1)) zin(i-1);  //向左
       f[c]=1; break;
     case 'H': //关羽可能的走步
       if(kgpd2(i+4))        zin(i+4);  //向下
       if(kgpd2(i-4))        zin(i-4);  //向上
       if(col<2&&kgpd(i+2)) {zin(i+1); if(h==2) zin(k1); }  //向右
       if(col  &&kgpd(i-1)) {zin(i-1); if(h==2) zin(k1); }  //向左
       f[c]=1; break;
     case 'C': //张飞,马超,赵云,黄忠可能的走步
       if(kgpd(i+8))        {zin(i+4); if(h==1) zin(k1); }  //向下
       if(kgpd(i-4))        {zin(i-4); if(h==1) zin(k1); }  //向上
       if(col<3&&kgpd1(i+1)) zin(i+1);  //向右
       if(col  &&kgpd1(i-1)) zin(i-1);  //向左
       f[c]=1; break;
     case 'B': //小兵可能的走步
       if(kgpd(i+4))        { if(h){zin(k1);zin(k2);} else zin(i+4); } //向上
       if(kgpd(i-4))        { if(h){zin(k1);zin(k2);} else zin(i-4); } //向下
       if(col<3&&kgpd(i+1)) { if(h){zin(k1);zin(k2);} else zin(i+1); } //向右
       if(col  &&kgpd(i-1)) { if(h){zin(k1);zin(k2);} else zin(i-1); } //向右
       break;
    }
  }
}
void zb(char *q,int s,int d){ //走一步函数
  char c=q[s],lx=U[c];
  switch(lx){
    case 'B': {q[s]=0;        q[d]=c;          break; }
    case 'C': {q[s]=q[s+4]=0; q[d]=q[d+4]=c;   break; }
    case 'H': {q[s]=q[s+1]=0; q[d]=q[d+1]=c;   break; }
    case 'M': {q[s]=q[s+1]=q[s+4]=q[s+5]=0; q[d]=q[d+1]=q[d+4]=q[d+5]=c; break; }
  }
}
//---------------------------------------------------------------------------
//--以下是搜索过程(广度优先)--
//---------------------------------------------------------------------------
class ZBD{ //走步队
 public:
 char (*z)[20];     //队列
 PMZB zbj;
 int n;       //队长度
 int *hs,*hss;//回溯用的指针及棋子
 int m,cur;   //队头及队头内步集游标,用于广度搜索
 int max;     //最大队长
 int *res,ren;//结果
 ZBD(int k){ z=new char[k][20]; hs=new int[k*2+500]; hss=hs+k; res=hss+k; max=k; reset(); }
 ~ZBD(){ delete[] z; delete[] hs;}
 void reset() { n=0; m=0,cur=-1; hss[n]=-1; ren=0;}
 int zbcd(char *q){ //走步出队
   if(cur==-1) zbFX(z[m],&zbj);
   cur++; if(cur>=zbj.n) {m++,cur=-1; return 1;} //步集游标控制
   if(hss[m]==zbj.s[cur]) return 1;//和上次移动同一个棋子时不搜索,可提速20%左右
   qpcpy(q,z[m]); zb(q,zbj.s[cur],zbj.d[cur]); //走步后产生新节点,结果放在qreturn 0;
 }
 void zbrd(char *q){ //走步入队
   if(n>=max) { printf("队溢出.\r\n"); return; }
   qpcpy(z[n],q); //出队
   if(cur>=0) hss[n]=zbj.d[cur]; //记录移动的子(用于回溯)
   hs[n++]=m; //记录回溯点
 }
 void hui(int cs){ //参数:层数
   int k=cs-2; ren=cs,res[cs-1]=m;
   for(;k>=0;k--) res[k]=hs[res[k+1]]; //回溯
 }
 char* getre(int n){ return z[res[n]];} //取第n步盘面

};
//--广度优先--
void bfs(char *q,int dep){ //参数为棋盘及搜索最大深度
  int i,j,k,bm,v; //ok表示是否找到
  int js=0,js2=0;
  PmBm Bm(q); //建立编码器
  char *JD=new char[Bm.bmtot]; qkmem(JD,Bm.bmtot); //建立节点数组
  ZBD Z=ZBD(Bm.bmtot/10); //建立队
  for(Z.zbrd(q),i=1;i<=dep;i++){ //一层一层的搜索
    k=Z.n;
    //printf("本层%d %d\r\n",i,k-Z.m);
    while(Z.m//广度优先
      if(Z.zbcd(q)) continue;     //返回1说明是步集出队,不是步出队
      js++;
      if(q[17]==15&&q[18]==15) { Z.hui(i); goto end; }//大王出来了
      if(i==dep) continue; //到了最后一层可以不再入队了
      bm=Bm.BM(q);
      if(!JD[bm]){
        js2++ ;  //js搜索总次数计数和js2遍历的实结点个数
        JD[bm]=1, JD[Bm.dcBM(q)]=1;//对节点及其对称点编码
        Z.zbrd(q);
      }
    }
  }
  end:delete JD;
  printf("共遍历%d个节点,其中实结点%d.队长%d,搜索层数%d,任意键...\r\n",js,js2,Z.n,Z.ren);
  if(!Z.ren) { printf("此局%d步内无解",dep); return; }
  for(i=0;iint argc, char* argv[])
{//华荣道棋盘参数,须留二个空位,兵41-4,竖将5-9,横将10-14,大王15(1个)
 char qp[20]={
   6,15,15,7,
   6,15,15,7,
   8,11,11,5,
   8,3, 4, 5,
   2,0, 0, 1
 };
 int i,dep=81;
 bfs(qp,dep);
 getch();
}
//---------------------------------------------------------------------------
//===============================================
//===============================================

七、利用哈希技术
用棋盘折叠方法计算哈希值
棋盘可看做5个int32,分别对它移位并求和,取得哈希值,移位应适当,充分利用各子,增强散列
让hash冲突变为零的要点:
1.利用盘面生成一个足够乱的数,你可能考虑各种各样的杂凑算法(类似MD5的功能)
折叠计算hash时,注意各子的值尽量少被直相加(异或等),折叠计算时通过适当移位后再相加,移位的作用是各子的数值部分尽量少重叠在一起,充分利用各子数值,产生足够的散列度.
2.利用随机函数(rand)来产生,当然随机数应与盘面产生关联,每一盘面对应的随机数(一个或一组)应是唯一的。
3.哈希表的大小应是表中记录的节点总数的4倍以上.
4.设哈希表为int hsb[128K+10],总节点数为m=30K
某一盘面节点的哈希值为n,n是17位的,那么n在hash表中位置为hsb[n],
hsb[n]里存放的是这个节点的另一个32位的哈希值,用于判断哈希冲突.
当出现冲突时,n在表中的位置改为n+1,这样可充分利用哈希表,节约空间
经过这样处理后,哈希冲突次数约为:
第一次哈希突次数:(1+2+…+30)/128=(n^2)/2/128=3.5k
第二次哈希突次数:(1*1+2*2+…+30*30)/(128*128)=(n^3)/3/128/128=0.55K
接下来我们再建第二个15位哈希表hsb2[32k]
同样上述处理
第三次哈希突次数:(1+2+…+0.55k)/32=(n^2)/2/32k=0.005k=5次
第四次哈希突次数:(1*1+2*2+…+0.55*0.55k)/(32k*32k)=0次
以上分析是在哈希值n的散列度理想情况下的结果,如果你的n的散列度不是很理想,冲突次数可乘上2,即:
第一次:3.5k*2=7k
第二次:0.55k*2=1.1
第三次:[(1+2+…+1.1k)/32]*2=40次
第四次:[(1*1+2*2+…+1.1*1.1k)/(32*32k)]*2=0.88次(约1次)

//===============================================
//===============================================
//===============================================
//下文是利用哈希技术优化后的代码
//===============================================

//---------------------------------------------------------------------------
//----本程序在C++Builder6.0及VC++6.0中调试通过----
//----程序名称:"华容道之哈希算法"搜索----
//----程序设计:许剑伟----
//----最后修改时间:2006.10.22----
//----速度:横刀立马12毫秒(P2.4G机器)
//---------------------------------------------------------------------------
#include 
#include 
#include 
#include 
//---------------------------------------------------------------------------
//--棋盘定义说明及搜索过程使用的核心数据结构--
//---------------------------------------------------------------------------
//棋盘表示使用char一维数组,例:char q[20];
//大王是5(大王只能1个),横将是4,竖将是3,兵是2,空位用0表示
//大王与横将前两个须相同,余占位填充1,竖将第二个占位同样填充1
//棋盘上只能为2个空格,不能多也不能少
//---------------------------------------------------------------------------
const COL[20]={0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3};//列号表
struct PMZB{       //盘面走步集结构
  char s[10],d[10];//原位置,目标位置,最多只会有10int n;           //总步数
};
typedef char QP[20];
//---------------------------------------------------------------------------
//--以下定义几函数--
//---------------------------------------------------------------------------
//以下define用于棋盘复制,不要用环循,实地址直接引用要快8#define qpcpy(q,p) {int *a=(int*)q,*b=(int*)p;a[0]=b[0],a[1]=b[1],a[2]=b[2],a[3]=b[3],a[4]=b[4];}/*复制棋盘*/
void qkmem(void *ps,int n){ //内存块置0,同memset(mem,0,memsize);
  register int *p=(int*)ps,*p2=p+n/4;
  while(p*p++=0;
  char *p3=(char *)p,*p4=(char *)ps+n;
  while(p3*p3++=0;
}
//---------------------------------------------------------------------------
//--以下是搜索算法之一(解决哈希表问题)--
//---------------------------------------------------------------------------
#define hsize 128*1024//使用128k(17位)哈希表,如果改用更大的表,相应的哈希计算位数也要改
//以下这两个哈希计算是对棋盘折叠计算,注意异或与加法相似,不会提高散列度,适当的移位则会提高散列度
#define hs17(h1,h) h=(h1&0x0001FFFF)^(h1>>17) //17位哈希值计算(折叠式计算)
#define hs15(h1,h) h=(h1&0x00007FFF)^(h1>>19) //15位哈希值计算(折叠式计算)
#define phs(h1,h,b){if(!b[h]){b[h]=h1;return 1;} if(b[h]==h1)return 0;h++;} //哈希值测试,返回1是新节点
class PmHx{ //盘面哈希计算
 public:
 unsigned int *hsb,*hsb2; //哈希表
 int cht; //哈希冲突次数
 PmHx(){//初始化编码表
   int i;
   hsb=new unsigned int[hsize+hsize/4+64];hsb2=hsb+hsize+32; //第二哈希表大小为第一哈希表的1/4
   reset();
 }
 ~PmHx(){ delete[] hsb; }
 void reset(){ cht=0; qkmem(hsb,(hsize+hsize/4+64)*sizeof(unsigned int));}
 int check(char *q){ //盘面编码
   //生成散列参数n1,n2,m0
   //以下参数生成算法不保证参数与棋盘的唯一对应关系,因此理论上存在哈希表冲突判断错误的可能
   //只不过产生错误的可能性几乎可能完全忽略
   unsigned int i,n1,n2,m0,h,h1,*p=(unsigned int*)q;
   n1=(p[1]<<3)+(p[2]<<5)+p[0]; //每次折叠时都应充分发挥各子作用,增强散列
   n2=(p[3]<<1)+(p[4]<<4);
   m0=(n2<<6)^(n1<<3); //增强散列参数
   int a=1;
   //第一哈希处理
   h1=n1+n2+m0; hs17(h1,h);//h1为散列和,h为第一哈希索引
   for(i=0;i<2;i++) phs(h1,h,hsb); //多次查表,最多32次
   //第二哈希处理
   h1=n1-n2+m0; hs15(h1,h);//h1为散列差,h为第二哈希值
   for(i=0;i<10;i++) phs(h1,h,hsb2); //首次查表
   cht++; //哈希冲突计数(通过5次哈希,一般情况下冲突次数为0)
   return 1;
 }
 void check2(char *q){ //按左右对称规则考查棋盘,并记录到哈希表
   char i,q2[20];
   for(i=0;i<20;i+=4) q2[i]=q[i+3],q2[i+1]=q[i+2],q2[i+2]=q[i+1],q2[i+3]=q[i];
   check(q2);
   //check2()执行次数较少,是实节点的次数,约为check()执行次数的1/3,所以不必过份求其速度
 }
}; //建立哈希表索引器
//---------------------------------------------------------------------------
//以下设计走法生成器
//---------------------------------------------------------------------------
#define zin0(des) z->s[z->n]=i,z->d[z->n++]=des //保存步法宏
#define zin1(des) z->s[z->n]=i-1,z->d[z->n++]=des-1 //保存步法宏(左移1列)
#define zin4(des) z->s[z->n]=i-4,z->d[z->n++]=des-4 //保存步法宏(上移1行)
#define zinb(des,fx) i=des+(fx); if(q[i]==2) {if(h){zin0(k1);zin0(k2);}else zin0(des);}
void zbFX(char *q,PMZB *z){ //分析当前可能的步法,并将所有可能的步法保存在z中
  int i,k1=-1,k2,h=0;z->n=0;  //k1空格1位置,k2空格2位置,h为两空格的联合类型,计步复位
  for(i=0;i<20;i++){ if(!q[i]){if(k1==-1) k1=i; else { k2=i; break; }} } //查空格的位置
  int col1=COL[k1],col2=COL[k2];
  if(k1+4==k2) h=1;         //空格竖联合
  if(k1+1==k2&&col1<3) h=2; //空格横联合
  if(col1>0){zinb(k1,-1);
    if(q[i]==3) {if(h==1) zin0(k1);}
    if(q[i]==5) {if(h==1) zin1(k1);}
    if(q[i]==4) {if(h==2) zin1(k2); zin1(k1);}
  }
  if(col1<3){zinb(k1,1);
    if(q[i]==3) {if(h==1) zin0(k1);}
    if(q[i]==5) {if(h==1) zin0(k1);}
    if(q[i]==4) {zin0(k1);} //如果横联合,k1不是第一空,所以不用判断h
  }
  if(k1>3){zinb(k1,-4);
    if(q[i]==4&&q[i+1]==4&&(col1!=1||q[i-1]!=4)){ if(h==2) zin0(k1); }
    if(q[i]==1){
      if(q[i-4]==3) {if(h==1) zin4(k2); zin4(k1);}
      if(q[i-4]==5&&q[i-3]==5){if(h==2) zin4(k1);}
    }
  }
  if(k1<16){zinb(k1,4);
    if(q[i]==3) zin0(k1);
    if(q[i]==4&&q[i+1]==4&&(col1!=1||q[i-1]!=4)){ if(h==2) zin0(k1); }
    if(q[i]==5&&q[i+1]==5){ if(h==2) zin0(k1); }
  }
  if(col2>0){zinb(k2,-1); if(q[i]==4) zin1(k2); }
  if(k2>3)  {zinb(k2,-4); if(q[i]==1&&q[i-4]==3)zin4(k2);}
  if(col2<3){zinb(k2,1);  if(q[i]==4) {if(h==2) zin0(k1); zin0(k2);}}
  if(k2<16) {zinb(k2,4);  if(q[i]==3) {if(h==1) zin0(k1); zin0(k2);}}
}
//---------------------------------------------------------------------------
//--以下是搜索过程(广度优先)--
//---------------------------------------------------------------------------
class ZBD{ //走步队(搜索器)
 public:
 QP *z;       //棋盘队列
 int dn,dm,cur;//队(队尾),队头及队头内走步集游标
 PMZB zbj;    //队头走步集
 int *hs;     //回溯用的指针,指向父亲(对应的父亲)
 char*hss;    //对应的源步
 int max;     //最大队长
 int *res,ren;//结果
 int js,js2;  //搜索情况计数
 PmHx Hx;     //希希处理类
 ZBD(int k){ z=new QP[k]; hs=new int[k*2+500]; res=hs+k; hss=new char[k]; max=k; reset(); }
 ~ZBD(){ delete[] z; delete[] hs; delete[] hss; }
 void reset() { dn=0; dm=0,cur=-1; ren=0; js=js2=0; hss[dn]=-1;}
 void zb(char *q,char s,char d){ //走一步函数
   char c=q[s];q[s]=0;
   switch(c){
    case 3: q[s+4]=0; q[d+4]=1; break; //竖,余位填充1
    case 4: q[s+1]=0; q[d+1]=c; break; //横
    case 5: q[s+1]=q[s+4]=q[s+5]=0; q[d+1]=c,q[d+4]=q[d+5]=1; break;
   }q[d]=c;
 }
 int zbcd(char *q){ //走步出队
   if(cur==-1) zbFX(z[dm],&zbj);
   cur++; if(cur>=zbj.n) {dm++,cur=-1; return 1;} //步集游标控制
   if(hss[dm]==zbj.s[cur]) return 1;//和上次移动同一个棋子时不搜索,可提速20%左右
   qpcpy(q,z[dm]); zb(q,zbj.s[cur],zbj.d[cur]); //走步后产生新节点,结果放在q中(出队)
   return 0;
 }
 void zbrd(char *q){ //走步入队
   if(dn>=max) { printf("队溢出.\r\n"); return; }
   qpcpy(z[dn],q); //出队
   if(cur>=0) hss[dn]=zbj.d[cur]; //记录下移动的目标位置(用于剪枝)
   hs[dn++]=dm; //记录回溯点
 }
 char* getre(int n){ return z[res[n]];} //取第n步盘面
 int bfs(char *qp,int dep,int all=0){ //广度优先搜索,参数为棋盘及搜索最大深度,all为穷举节点总数
  if(dep>500||dep<=0) dep=200;
  reset(); Hx.reset(); //哈希表及队复位
  char q[20]; qpcpy(q,qp);
  int i,k;
  for(zbrd(q),i=1;i<=dep;i++){ //一层一层的搜索
    k=dn; if(dm==k) return -1;
    if(all)printf("第%d层共%d节点\r\n",i-1,k-dm);
    while(dm//广度优先
      if(zbcd(q)) continue;     //返回1说明是步集出队,不是步出队
      js++; //遍历总次数计数
      if(q[13]==5&&q[14]==5&&!all) { //大王出来了
        for(ren=i,k=ren-2,res[ren-1]=dm;k>=0;k--) res[k]=hs[res[k+1]]; //回溯
        return 1;
      }
      if(iq)){ //到了最后一层可以不再入队了
        js2++;       //js2遍历的实结点个数,js2不包括起始点,出队时阻止了回头步,始节点不可能再遍历
        Hx.check2(q);//对称节点做哈希处理
        zbrd(q);
      }
    }
  }
  return 0;
 }
}S(40*1024); //建立搜索引擎
//---------------------------------------------------------------------------
//----输入输出部分----
//---------------------------------------------------------------------------
void prt(char *q){ //打印棋盘
  int i,j,k;
  char y[20],x[20],xy[20],p[20],c1,c2;
  for(i=0;i<20;i++){
    y[i]='|',x[i]='-',xy[i]='+';
    if(q[i]) p[i]=q[i]+48; else p[i]=' ';
    if(q[i]==1) p[i]=p[i-4];
  }
  for(i=0;i<20;i++){
    if(q[i]==0) {if(COL[i]<3&&q[i+1]==0) y[i]=' '; if(i<16&&q[i+4]==0) x[i]=' ';}
    if(q[i]==3) { x[i]='.'; }
    if(q[i]==4) { y[i]='.'; i++; }
    if(q[i]==5) { y[i]=' '; y[i+4]=' '; x[i]=' '; x[i+1]=' '; xy[i]='.'; i++; }
  }
  printf("+-+-+-+-+\r\n");
  for(i=0;i<5;i++){
    k=i*4;
    printf("|");
    for(j=0;j<4;j++){ printf("%c%c",p[k+j],y[k+j]); }
    printf("\r\n|");
    for(j=0;j<4;j++){ printf("%c%c",x[k+j],xy[k+j]); }
    printf("\r\n");
  }
}
//---------------------------------------------------------------------------
void main(int argc, char* argv[]){
 int i,ok,t1=clock();
 QP qp={
   3,5,5,3,
   1,1,1,1,
   3,4,4,3,
   1,2,2,1,
   2,0,0,2
 };
 ok=S.bfs(qp,500);
 if(!ok) printf("此局500层内无解.\r\n");
 if(ok==-1) printf("此局无解.\r\n",200);
 printf("%d层有解,遍历%d节点,哈希%d节点,队长%d,哈希冲突%d次,用时%dms\r\n",S.ren,S.js,S.js2,S.dn,S.Hx.cht,clock()-t1);
 for(i=0;iprintf("第%d步(ESC退出)\r\n",i);
   prt(S.getre(i));
   if(getch()==27) break;
   clrscr();
 }
 getch();
}
//---------------------------------------------------------------------------

八、利用javascript进行华荣道搜索

//===============================================
//===============================================
//===============================================
//下文是利用javascript进行华容道搜索
//速度:约25秒(P2.4G)
//设计:许剑伟,200655日下午及晚上—200656日上午
//===============================================


华容道<<span class="hljs-regexp">/title>
</head</span>>

<body>
<script language=javascript>
var QZLX=Array();<span class="hljs-regexp">//</span>棋子类型表
QZLX.A=<span class="hljs-string">"A"</span>;
QZLX.B=<span class="hljs-string">"B"</span>;
QZLX.X=<span class="hljs-string">"B"</span>;
QZLX.Y=<span class="hljs-string">"B"</span>;
QZLX.Z=<span class="hljs-string">"B"</span>;
QZLX.C=<span class="hljs-string">"C"</span>;QZLX.D=<span class="hljs-string">"C"</span>;QZLX.E=<span class="hljs-string">"C"</span>;QZLX.F=<span class="hljs-string">"C"</span>;QZLX.G=<span class="hljs-string">"C"</span>;
QZLX.H=<span class="hljs-string">"H"</span>;QZLX.I=<span class="hljs-string">"H"</span>;QZLX.J=<span class="hljs-string">"H"</span>;QZLX.K=<span class="hljs-string">"H"</span>;QZLX.L=<span class="hljs-string">"H"</span>;
QZLX.M=<span class="hljs-string">"M"</span>;
var COL=Array(<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>); <span class="hljs-regexp">//</span>列号表
var ROW=Array(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">2</span>,<span class="hljs-number">2</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">3</span>,<span class="hljs-number">3</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">4</span>,<span class="hljs-number">4</span>,<span class="hljs-number">4</span>); <span class="hljs-regexp">//</span>行号表
qp=Array(
 <span class="hljs-string">"C"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"D"</span>,
 <span class="hljs-string">"C"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"D"</span>,
 <span class="hljs-string">"E"</span>,<span class="hljs-string">"H"</span>,<span class="hljs-string">"H"</span>,<span class="hljs-string">"F"</span>,
 <span class="hljs-string">"E"</span>,<span class="hljs-string">"X"</span>,<span class="hljs-string">"Y"</span>,<span class="hljs-string">"F"</span>,
 <span class="hljs-string">"B"</span>,<span class="hljs-string">"A"</span>,<span class="hljs-string">"A"</span>,<span class="hljs-string">"Z"</span>
// <span class="hljs-string">"B"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"B"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"E"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"F"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"E"</span>,<span class="hljs-string">"H"</span>,<span class="hljs-string">"H"</span>,<span class="hljs-string">"F"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"B"</span>,<span class="hljs-string">"I"</span>,<span class="hljs-string">"I"</span>,<span class="hljs-string">"B"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"A"</span>,<span class="hljs-string">"J"</span>,<span class="hljs-string">"J"</span>,<span class="hljs-string">"A"</span>
// <span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"A"</span>,<span class="hljs-string">"C"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"M"</span>,<span class="hljs-string">"M"</span>,<span class="hljs-string">"A"</span>,<span class="hljs-string">"C"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"D"</span>,<span class="hljs-string">"E"</span>,<span class="hljs-string">"H"</span>,<span class="hljs-string">"H"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"D"</span>,<span class="hljs-string">"E"</span>,<span class="hljs-string">"B"</span>,<span class="hljs-string">"F"</span>,
<span class="hljs-regexp">//</span> <span class="hljs-string">"B"</span>,<span class="hljs-string">"B"</span>,<span class="hljs-string">"B"</span>,<span class="hljs-string">"F"</span>
);

function qpToS(<span class="hljs-keyword">q</span>){ <span class="hljs-regexp">//</span>棋盘转为串
  var i,j,<span class="hljs-keyword">s</span>=<span class="hljs-string">""</span>;
  <span class="hljs-keyword">for</span>(i=<span class="hljs-number">0</span>;i<<span class="hljs-number">5</span>;i++,<span class="hljs-keyword">s</span>+=<span class="hljs-string">"<br>"</span>)
    <span class="hljs-keyword">for</span>(j=<span class="hljs-number">0</span>;j<<span class="hljs-number">4</span>;j++) <span class="hljs-keyword">s</span>+=<span class="hljs-string">q[i<span class="hljs-variable">*4</span>+j]</span>+<span class="hljs-string">" "</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">s</span>.replace(<span class="hljs-regexp">/[A]/g</span>,<span class="hljs-string">" "</span>);
}
function BM(<span class="hljs-keyword">q</span>){   <span class="hljs-regexp">//</span>快速编码
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">q</span>.<span class="hljs-keyword">join</span>(<span class="hljs-string">""</span>).replace(<span class="hljs-regexp">/[DEFG]/g</span>,<span class="hljs-string">"C"</span>).replace(<span class="hljs-regexp">/[IJKL]/g</span>,<span class="hljs-string">"H"</span>).replace(<span class="hljs-regexp">/[XYZ]/g</span>,<span class="hljs-string">"B"</span>);
}
function dcBM(<span class="hljs-keyword">q</span>){ <span class="hljs-regexp">//</span>对称编码
  var <span class="hljs-keyword">s</span>=<span class="hljs-string">q[3]</span>+<span class="hljs-string">q[2]</span>+<span class="hljs-string">q[1]</span>+<span class="hljs-string">q[0]</span>+<span class="hljs-string">q[7]</span>+<span class="hljs-string">q[6]</span>+<span class="hljs-string">q[5]</span>+<span class="hljs-string">q[4]</span>+<span class="hljs-string">q[11]</span>+<span class="hljs-string">q[10]</span>+<span class="hljs-string">q[9]</span>+<span class="hljs-string">q[8]</span>+<span class="hljs-string">q[15]</span>+<span class="hljs-string">q[14]</span>+<span class="hljs-string">q[13]</span>+<span class="hljs-string">q[12]</span>+<span class="hljs-string">q[19]</span>+<span class="hljs-string">q[18]</span>+<span class="hljs-string">q[17]</span>+<span class="hljs-string">q[16]</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">s</span>.replace(<span class="hljs-regexp">/[DEFG]/g</span>,<span class="hljs-string">"C"</span>).replace(<span class="hljs-regexp">/[IJKL]/g</span>,<span class="hljs-string">"H"</span>).replace(<span class="hljs-regexp">/[XYZ]/g</span>,<span class="hljs-string">"B"</span>);
}
function zbFX(<span class="hljs-keyword">q</span>){ <span class="hljs-regexp">//</span>走步分析
  var i,r=<span class="hljs-string">""</span>;
  <span class="hljs-keyword">for</span>(i in <span class="hljs-keyword">q</span>){ <span class="hljs-regexp">//i</span>是字符型
    <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-0]</span>!=<span class="hljs-string">"A"</span>) <span class="hljs-keyword">continue</span>;
    i=i-<span class="hljs-number">0</span>;
    <span class="hljs-keyword">if</span>(ROW[i]<<span class="hljs-number">4</span>){
      switch(QZLX[<span class="hljs-string">q[i+4]</span>]){ <span class="hljs-regexp">//</span>下棋子
        case <span class="hljs-string">"B"</span>: { r+=i+<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"C"</span>: { r+=i+<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"H"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">q[i+5]</span>&&<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>) { r+=i+<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"M"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">q[i+5]</span>&&<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>) { r+=i+<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }
      }
      <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>&&ROW[i]<<span class="hljs-number">3</span>){ <span class="hljs-regexp">//</span>处理下二棋子
        switch(QZLX[<span class="hljs-string">q[i+8]</span>]){
          case <span class="hljs-string">"C"</span>: { r+=i+<span class="hljs-number">8</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
          case <span class="hljs-string">"B"</span>: { r+=i+<span class="hljs-number">8</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }
        }
      }
    }
    <span class="hljs-keyword">if</span>(ROW[i]){
      switch(QZLX[<span class="hljs-string">q[i-4]</span>]){ <span class="hljs-regexp">//</span>上棋子
        case <span class="hljs-string">"B"</span>: { r+=i-<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"C"</span>: { r+=i-<span class="hljs-number">8</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">4</span>)+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"H"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-4]</span>==<span class="hljs-string">q[i-3]</span>&&<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>) { r+=i-<span class="hljs-number">4</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"M"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-4]</span>==<span class="hljs-string">q[i-3]</span>&&<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>) { r+=i-<span class="hljs-number">8</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">4</span>)+<span class="hljs-string">" "</span>; }
      }
      <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-4]</span>==<span class="hljs-string">"A"</span>&&ROW[i]><span class="hljs-number">1</span>){ <span class="hljs-regexp">//</span>处理上二棋子
        switch(QZLX[<span class="hljs-string">q[i-8]</span>]){
          case <span class="hljs-string">"C"</span>: { r+=i-<span class="hljs-number">12</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">4</span>)+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
          case <span class="hljs-string">"B"</span>: { r+=i-<span class="hljs-number">8</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }
        }
      }
    }
    <span class="hljs-keyword">if</span>(COL[i]){ <span class="hljs-regexp">//</span>处理左边棋子
      switch(QZLX[<span class="hljs-string">q[i-1]</span>]){ <span class="hljs-regexp">//</span>左棋子
        case <span class="hljs-string">"B"</span>: { r+=i-<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"H"</span>: { r+=i-<span class="hljs-number">2</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">1</span>)+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"C"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-1]</span>==<span class="hljs-string">q[i+3]</span>&&<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>) { r+=i-<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"M"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-1]</span>==<span class="hljs-string">q[i+3]</span>&&<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>) { r+=i-<span class="hljs-number">2</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">1</span>)+<span class="hljs-string">" "</span>; }

      }
      <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i-1]</span>==<span class="hljs-string">"A"</span>&&COL[i]><span class="hljs-number">1</span>){ <span class="hljs-regexp">//</span>处理左二棋子
        switch(QZLX[<span class="hljs-string">q[i-2]</span>]){
          case <span class="hljs-string">"H"</span>: { r+=i-<span class="hljs-number">3</span>+<span class="hljs-string">" "</span>+(i-<span class="hljs-number">1</span>)+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
          case <span class="hljs-string">"B"</span>: { r+=i-<span class="hljs-number">2</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }
        }
      }
      <span class="hljs-keyword">if</span>(QZLX[<span class="hljs-string">q[i-5]</span>]==<span class="hljs-string">"B"</span>&&(<span class="hljs-string">q[i-1]</span>==<span class="hljs-string">"A"</span>||<span class="hljs-string">q[i-4]</span>==<span class="hljs-string">"A"</span>)) { r+=i-<span class="hljs-number">5</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; } //左上方棋子
      <span class="hljs-keyword">if</span>(QZLX[<span class="hljs-string">q[i+3]</span>]==<span class="hljs-string">"B"</span>&&(<span class="hljs-string">q[i-1]</span>==<span class="hljs-string">"A"</span>||<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>)) { r+=i+<span class="hljs-number">3</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; } //左下方棋子
    }
    <span class="hljs-keyword">if</span>(COL[i]<<span class="hljs-number">3</span>){ <span class="hljs-regexp">//</span>处理右边棋子
      switch(QZLX[<span class="hljs-string">q[i+1]</span>]){ <span class="hljs-regexp">//</span>右棋子
        case <span class="hljs-string">"B"</span>: { r+=i+<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"H"</span>: { r+=i+<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"C"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">q[i+5]</span>&&<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>) { r+=i+<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
        case <span class="hljs-string">"M"</span>: <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">q[i+5]</span>&&<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>) { r+=i+<span class="hljs-number">1</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }

      }
      <span class="hljs-keyword">if</span>(<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>&&COL[i]<<span class="hljs-number">2</span>){ <span class="hljs-regexp">//</span>处理右二棋子
        switch(QZLX[<span class="hljs-string">q[i+2]</span>]){
          case <span class="hljs-string">"H"</span>: { r+=i+<span class="hljs-number">2</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; <span class="hljs-keyword">break</span>; }
          case <span class="hljs-string">"B"</span>: { r+=i+<span class="hljs-number">2</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; }
        }
      }
      <span class="hljs-keyword">if</span>(QZLX[<span class="hljs-string">q[i-3]</span>]==<span class="hljs-string">"B"</span>&&(<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>||<span class="hljs-string">q[i-4]</span>==<span class="hljs-string">"A"</span>)) { r+=i-<span class="hljs-number">3</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; } //右上方棋子
      <span class="hljs-keyword">if</span>(QZLX[<span class="hljs-string">q[i+5]</span>]==<span class="hljs-string">"B"</span>&&(<span class="hljs-string">q[i+1]</span>==<span class="hljs-string">"A"</span>||<span class="hljs-string">q[i+4]</span>==<span class="hljs-string">"A"</span>)) { r+=i+<span class="hljs-number">5</span>+<span class="hljs-string">" "</span>+i+<span class="hljs-string">" "</span>; } //右下方棋子
    }
  }
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">q</span>.<span class="hljs-keyword">join</span>(<span class="hljs-string">" "</span>)+<span class="hljs-string">" "</span>+r; <span class="hljs-regexp">//</span>为防止对象过多,干脆用一个单串返回
}
function zb(<span class="hljs-keyword">q</span>,<span class="hljs-keyword">s</span>,d){
  var c=<span class="hljs-string">q[s]</span>;
  switch(QZLX[c]){
    case <span class="hljs-string">"B"</span>: {<span class="hljs-string">q[s]</span>=<span class="hljs-string">"A"</span>;                      <span class="hljs-string">q[d]</span>=c;        <span class="hljs-keyword">break</span>; }
    case <span class="hljs-string">"C"</span>: {<span class="hljs-string">q[s]</span>=<span class="hljs-string">q[s+4]</span>=<span class="hljs-string">"A"</span>;               <span class="hljs-string">q[d]</span>=<span class="hljs-string">q[d+4]</span>=c; <span class="hljs-keyword">break</span>; }
    case <span class="hljs-string">"H"</span>: {<span class="hljs-string">q[s]</span>=<span class="hljs-string">q[s+1]</span>=<span class="hljs-string">"A"</span>;               <span class="hljs-string">q[d]</span>=<span class="hljs-string">q[d+1]</span>=c; <span class="hljs-keyword">break</span>; }
    case <span class="hljs-string">"M"</span>: {<span class="hljs-string">q[s]</span>=<span class="hljs-string">q[s+1]</span>=<span class="hljs-string">q[s+4]</span>=<span class="hljs-string">q[s+5]</span>=<span class="hljs-string">"A"</span>; <span class="hljs-string">q[d]</span>=<span class="hljs-string">q[d+1]</span>=<span class="hljs-string">q[d+4]</span>=<span class="hljs-string">q[d+5]</span>=c; <span class="hljs-keyword">break</span>; }
  }
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">q</span>;
}
//------------------------------------
function ZBD(){ <span class="hljs-regexp">//</span>构造走步队对象
  this.z=Array();  <span class="hljs-regexp">//</span>队列,this为当前对象,常在构造时使用,在没有用new分配一个实体前,this不明确
  this.hs=Array(); <span class="hljs-regexp">//</span>回朔指针
  this.hsb=Array(); <span class="hljs-regexp">//</span>回朔步
  this.hd=<span class="hljs-number">0</span>;       <span class="hljs-regexp">//</span>队头指针
  this.cur=Array();<span class="hljs-regexp">//</span>队头信息
  this.Rd=zbrd;    <span class="hljs-regexp">//</span>入队方法
  this.Cd=zbcd;    <span class="hljs-regexp">//</span>出队方法
  this.getQP=getqp;
  this.cur.n=<span class="hljs-string">"null"</span>; <span class="hljs-regexp">//cur</span>无内容标记

}
function zbrd(<span class="hljs-keyword">q</span>,fla){ <span class="hljs-regexp">//</span>走步入队,第二个参数为是否回朔
  var n=this.z.<span class="hljs-keyword">length</span>;
  this.z[n]=zbFX(<span class="hljs-keyword">q</span>);
  <span class="hljs-keyword">if</span>(fla==-<span class="hljs-number">1</span>) this.hs[n]=<span class="hljs-number">0</span>,this.hsb[n]=<span class="hljs-string">"无棋子"</span>;<span class="hljs-regexp">//</span>回朔指针
  <span class="hljs-keyword">else</span> this.hs[n]=this.hd,this.hsb[n]=this.cur[this.cur[this.cur.p-<span class="hljs-number">2</span>]];
}
function zbcd(){ <span class="hljs-regexp">//</span>走步出队
  <span class="hljs-keyword">if</span>(this.cur.n==<span class="hljs-string">"null"</span>){
    this.cur=this.z[this.hd].<span class="hljs-keyword">split</span>(<span class="hljs-string">" "</span>);
    this.cur.n=this.cur.<span class="hljs-keyword">length</span>-<span class="hljs-number">1</span>;<span class="hljs-regexp">//</span>原串中最后一个是空格所以多减<span class="hljs-number">1</span>
    this.cur.p=<span class="hljs-number">20</span>; <span class="hljs-regexp">//</span>棋步游标
  }
  <span class="hljs-keyword">if</span>(this.cur.p>=this.cur.n) {this.hd++; this.cur.n=<span class="hljs-string">"null"</span>; <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;}
  var p=this.cur.p;
  this.cur.p+=<span class="hljs-number">2</span>;
  <span class="hljs-keyword">if</span>(this.cur[this.cur[p]]==this.hsb[this.hd]) <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  <span class="hljs-keyword">return</span> zb(this.cur.slice(<span class="hljs-number">0</span>,<span class="hljs-number">20</span>),this.cur[p]-<span class="hljs-number">0</span>,this.cur[p+<span class="hljs-number">1</span>]-<span class="hljs-number">0</span>); <span class="hljs-regexp">//</span>使用拷贝盘传入
}
function getqp(n){ <span class="hljs-regexp">//</span>从队中取出棋盘
  var <span class="hljs-keyword">s</span>=this.z[n].<span class="hljs-keyword">split</span>(<span class="hljs-string">" "</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">s</span>.slice(<span class="hljs-number">0</span>,<span class="hljs-number">20</span>);
}
//------------------------------------
<span class="hljs-regexp">//</span>广度优先搜索
//------------------------------------

function GDsearch(<span class="hljs-keyword">q</span>,dep){ <span class="hljs-regexp">//</span>参数为棋盘及搜索最大深度
  var i,k,ok=<span class="hljs-number">0</span>,bm,v; <span class="hljs-regexp">//ok</span>表示是否找到
  var js=<span class="hljs-number">0</span>,js2=<span class="hljs-number">0</span>;
  var D=new ZBD(); <span class="hljs-regexp">//</span>建立走步队
  var JD=Array();  <span class="hljs-regexp">//</span>结点记录器
  <span class="hljs-keyword">for</span>(D.Rd(<span class="hljs-keyword">q</span>,-<span class="hljs-number">1</span>),i=<span class="hljs-number">1</span>;i<=dep&&!ok;i++){ <span class="hljs-regexp">//</span>一层一层的搜索
    k=D.z.<span class="hljs-keyword">length</span>;
    <span class="hljs-keyword">while</span>(D.hd<k){ <span class="hljs-regexp">//</span>广度优先
      <span class="hljs-keyword">q</span>=D.Cd(); <span class="hljs-regexp">//</span>出队
      <span class="hljs-keyword">if</span>(<span class="hljs-keyword">q</span>==<span class="hljs-string">""</span>) <span class="hljs-keyword">continue</span>;     <span class="hljs-regexp">//</span>返回空说明是步集出队,不是步出队
      <span class="hljs-keyword">if</span>(<span class="hljs-string">q[17]</span>==<span class="hljs-string">"M"</span>&&<span class="hljs-string">q[18]</span>==<span class="hljs-string">"M"</span>) { ok=<span class="hljs-number">1</span>;<span class="hljs-keyword">break</span>;} //大王出来了
      <span class="hljs-keyword">if</span>(i==dep) <span class="hljs-keyword">continue</span>; <span class="hljs-regexp">//</span>到了最后一层就不再入队了
      bm=BM(<span class="hljs-keyword">q</span>); v=JD[bm];
      js++;
      <span class="hljs-keyword">if</span>(!v){
        js2++ ;  <span class="hljs-regexp">//js</span>搜索总次数计数和js2遍历的实结点个数
        JD[bm]=i, JD[dcBM(<span class="hljs-keyword">q</span>)]=i;<span class="hljs-regexp">//</span>对节点及其对称点编码并计录结点深度
        D.Rd(<span class="hljs-keyword">q</span>,<span class="hljs-number">0</span>);  <span class="hljs-regexp">//</span>入队
      }
    }
  }
  k=i-<span class="hljs-number">1</span>; <span class="hljs-regexp">//</span>实际计算的层数
  var <span class="hljs-keyword">s</span>=<span class="hljs-string">"共遍历"</span>+js+<span class="hljs-string">"个节点,其中实结点"</span>+js2+<span class="hljs-string">"搜索步数"</span>+k+<span class="hljs-string">"<hr>"</span>;
  var hs=Array();
  <span class="hljs-keyword">if</span>(ok){
    <span class="hljs-keyword">for</span>(i=<span class="hljs-number">1</span>,hs[<span class="hljs-number">0</span>]=D.hd;i<k;i++) hs[i]=D.hs[hs[i-<span class="hljs-number">1</span>]]; <span class="hljs-regexp">//</span>回塑
    <span class="hljs-keyword">for</span>(i=k-<span class="hljs-number">1</span>;i>=<span class="hljs-number">0</span>;i--)  <span class="hljs-keyword">s</span>+=qpToS(D.getQP(hs[i]))+<span class="hljs-string">"<hr>"</span>;
    <span class="hljs-keyword">s</span>+=qpToS(<span class="hljs-keyword">q</span>);
  }
  <span class="hljs-keyword">else</span> <span class="hljs-keyword">s</span>+=<span class="hljs-string">"此局"</span>+dep+<span class="hljs-string">"步内无解"</span>;
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">s</span>;
}
document.<span class="hljs-keyword">write</span>(GDsearch(qp,<span class="hljs-number">130</span>));

<<span class="hljs-regexp">/script>
</body</span>>

<<span class="hljs-regexp">/html></span></code></pre> 
 </div> 
</div>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1188218768917110784"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(华容道搜索算法研究)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1835514307744460800.htm"
                           title="QQ群采集助手,精准引流必备神器" target="_blank">QQ群采集助手,精准引流必备神器</a>
                        <span class="text-muted">2401_87347160</span>
<a class="tag" taget="_blank" href="/search/%E5%85%B6%E4%BB%96/1.htm">其他</a><a class="tag" taget="_blank" href="/search/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/1.htm">经验分享</a>
                        <div>功能概述微信群查找与筛选工具是一款专为微信用户设计的辅助工具,它通过关键词搜索功能,帮助用户快速找到相关的微信群,并提供筛选是否需要验证的群组的功能。主要功能关键词搜索:用户可以输入关键词,工具将自动查找包含该关键词的微信群。筛选功能:工具提供筛选机制,用户可以选择是否只显示需要验证或不需要验证的群组。精准引流:通过上述功能,用户可以更精准地找到目标群组,进行有效的引流操作。3.设备需求该工具可以</div>
                    </li>
                    <li><a href="/article/1835497664922349568.htm"
                           title="使用Faiss进行高效相似度搜索" target="_blank">使用Faiss进行高效相似度搜索</a>
                        <span class="text-muted">llzwxh888</span>
<a class="tag" taget="_blank" href="/search/faiss/1.htm">faiss</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a>
                        <div>在现代AI应用中,快速和高效的相似度搜索是至关重要的。Faiss(FacebookAISimilaritySearch)是一个专门用于快速相似度搜索和聚类的库,特别适用于高维向量。本文将介绍如何使用Faiss来进行相似度搜索,并结合Python代码演示其基本用法。什么是Faiss?Faiss是一个由FacebookAIResearch团队开发的开源库,主要用于高维向量的相似性搜索和聚类。Faiss</div>
                    </li>
                    <li><a href="/article/1835493247179386880.htm"
                           title="Faiss Tips:高效向量搜索与聚类的利器" target="_blank">Faiss Tips:高效向量搜索与聚类的利器</a>
                        <span class="text-muted">焦习娜Samantha</span>

                        <div>FaissTips:高效向量搜索与聚类的利器faiss_tipsSomeusefultipsforfaiss项目地址:https://gitcode.com/gh_mirrors/fa/faiss_tips项目介绍Faiss是由FacebookAIResearch开发的一个用于高效相似性搜索和密集向量聚类的库。它支持多种硬件平台,包括CPU和GPU,能够在海量数据集上实现快速的近似最近邻搜索(AN</div>
                    </li>
                    <li><a href="/article/1835488702881689600.htm"
                           title="Faiss:高效相似性搜索与聚类的利器" target="_blank">Faiss:高效相似性搜索与聚类的利器</a>
                        <span class="text-muted">网络·魚</span>
<a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/faiss/1.htm">faiss</a>
                        <div>Faiss是一个针对大规模向量集合的相似性搜索库,由FacebookAIResearch开发。它提供了一系列高效的算法和数据结构,用于加速向量之间的相似性搜索,特别是在大规模数据集上。本文将介绍Faiss的原理、核心功能以及如何在实际项目中使用它。Faiss原理:近似最近邻搜索:Faiss的核心功能之一是近似最近邻搜索,它能够高效地在大规模数据集中找到与给定查询向量最相似的向量。这种搜索是近似的,</div>
                    </li>
                    <li><a href="/article/1835478881671409664.htm"
                           title="容易满足的小孩" target="_blank">容易满足的小孩</a>
                        <span class="text-muted">洒在心头的阳光</span>

                        <div>去年买的榨汁机没有用几次就坏了,前些时间答应娃儿给他买个,天天没事就问我,啥时候买,还自己淘宝上比较,加入购物车,这不前几天赶紧给他买了,省的每天叨叨在我耳边念叨着。今天终于到货了,因为他一直想和喝芒果汁,顺便买了芒果在家,放学回来兴奋的,赶紧要榨芒果汁,还特意搜索一下芒果汁的做法,我说他要是学习能有吃这般如此认真,我也就没有那么操心了。今晚喝到了芒果汁,他很开心,是阿,孩子就是这么容易满足,得到</div>
                    </li>
                    <li><a href="/article/1835469859710922752.htm"
                           title="母亲节如何做小红书营销" target="_blank">母亲节如何做小红书营销</a>
                        <span class="text-muted">美橙传媒</span>

                        <div>小红书的一举一动引起了外界的高度关注。通过爆款笔记和流行话题,我们可以看到“干货”类型的内容在小红书中偏向实用的生活经验共享和生活指南非常受欢迎。根据运营社的分析,这种现象是由小红书用户心智和内容社区背后机制共同决定的。首先,小红书将使用“强搜索”逻辑为用户提供特定的“搜索场景”。在“我必须这样生活”中,大量使用了满足小红书站用户喜好和需求的内容。内容社区自制的高质量内容也吸引了寻找营销新途径的品</div>
                    </li>
                    <li><a href="/article/1835463115882459136.htm"
                           title="2024.9.6 Python,华为笔试题总结,字符串格式化,字符串操作,广度优先搜索解决公司组织绩效互评问题,无向图" target="_blank">2024.9.6 Python,华为笔试题总结,字符串格式化,字符串操作,广度优先搜索解决公司组织绩效互评问题,无向图</a>
                        <span class="text-muted">RaidenQ</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/1.htm">华为</a><a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%8A%9B%E6%89%A3/1.htm">力扣</a><a class="tag" taget="_blank" href="/search/%E5%B9%BF%E5%BA%A6%E4%BC%98%E5%85%88/1.htm">广度优先</a><a class="tag" taget="_blank" href="/search/%E6%97%A0%E5%90%91%E5%9B%BE/1.htm">无向图</a>
                        <div>1.字符串格式化name="Alice"age=30formatted_string="Name:{},Age:{}".format(name,age)print(formatted_string)或者name="Alice"age=30formatted_string=f"Name:{name},Age:{age}"print(formatted_string)2.网络健康检查第一行有两个整数m</div>
                    </li>
                    <li><a href="/article/1835454921990828032.htm"
                           title="Java爬虫框架(一)--架构设计" target="_blank">Java爬虫框架(一)--架构设计</a>
                        <span class="text-muted">狼图腾-狼之传说</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E4%BB%BB%E5%8A%A1/1.htm">任务</a><a class="tag" taget="_blank" href="/search/html%E8%A7%A3%E6%9E%90%E5%99%A8/1.htm">html解析器</a><a class="tag" taget="_blank" href="/search/%E5%AD%98%E5%82%A8/1.htm">存储</a><a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E5%95%86%E5%8A%A1/1.htm">电子商务</a>
                        <div>一、架构图那里搜网络爬虫框架主要针对电子商务网站进行数据爬取,分析,存储,索引。爬虫:爬虫负责爬取,解析,处理电子商务网站的网页的内容数据库:存储商品信息索引:商品的全文搜索索引Task队列:需要爬取的网页列表Visited表:已经爬取过的网页列表爬虫监控平台:web平台可以启动,停止爬虫,管理爬虫,task队列,visited表。二、爬虫1.流程1)Scheduler启动爬虫器,TaskMast</div>
                    </li>
                    <li><a href="/article/1835454543471669248.htm"
                           title="Java:爬虫框架" target="_blank">Java:爬虫框架</a>
                        <span class="text-muted">dingcho</span>
<a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a>
                        <div>一、ApacheNutch2【参考地址】Nutch是一个开源Java实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。Nutch致力于让每个人能很容易,同时花费很少就可以配置世界一流的Web搜索引擎.为了完成这一宏伟的目标,Nutch必须能够做到:每个月取几十亿网页为这些网页维护一个索引对索引文件进行每秒上千次的搜索提供高质量的搜索结果简单来说Nutch支持分</div>
                    </li>
                    <li><a href="/article/1835444957423431680.htm"
                           title="《 C++ 修炼全景指南:九 》打破编程瓶颈!掌握二叉搜索树的高效实现与技巧" target="_blank">《 C++ 修炼全景指南:九 》打破编程瓶颈!掌握二叉搜索树的高效实现与技巧</a>
                        <span class="text-muted">Lenyiin</span>
<a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E4%BF%AE%E7%82%BC%E5%85%A8%E6%99%AF%E6%8C%87%E5%8D%97/1.htm">修炼全景指南</a><a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%8C%87%E5%8D%97/1.htm">技术指南</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/stl/1.htm">stl</a>
                        <div>摘要本文详细探讨了二叉搜索树(BinarySearchTree,BST)的核心概念和技术细节,包括插入、查找、删除、遍历等基本操作,并结合实际代码演示了如何实现这些功能。文章深入分析了二叉搜索树的性能优势及其时间复杂度,同时介绍了前驱、后继的查找方法等高级功能。通过自定义实现的二叉搜索树类,读者能够掌握其实际应用,此外,文章还建议进一步扩展为平衡树(如AVL树、红黑树)以优化极端情况下的性能退化。</div>
                    </li>
                    <li><a href="/article/1835436390200995840.htm"
                           title="Table列表复现框实现【勾选-搜索-再勾选】" target="_blank">Table列表复现框实现【勾选-搜索-再勾选】</a>
                        <span class="text-muted">~四时春~</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/elementui/1.htm">elementui</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a>
                        <div>Table列表复现框实现【勾选-搜索-再勾选】概要整体架构流程代码实现技术细节注意参考文献概要最近在开发时遇到一个问题,在进行表单渲染时,正常选中没有问题,单如果需要搜索选中时,一个是已选中的不会回填,二是在搜索的结果中进行选中,没有实现,经过排查,查找资料后实现。例如:整体架构流程具体的实现效果如下:代码实现{{scope.row.userName}}已选区{{userItem.userName</div>
                    </li>
                    <li><a href="/article/1835435380267118592.htm"
                           title="《 C++ 修炼全景指南:十 》自平衡的艺术:深入了解 AVL 树的核心原理与实现" target="_blank">《 C++ 修炼全景指南:十 》自平衡的艺术:深入了解 AVL 树的核心原理与实现</a>
                        <span class="text-muted">Lenyiin</span>
<a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/%E4%BF%AE%E7%82%BC%E5%85%A8%E6%99%AF%E6%8C%87%E5%8D%97/1.htm">修炼全景指南</a><a class="tag" taget="_blank" href="/search/%E6%8A%80%E6%9C%AF%E6%8C%87%E5%8D%97/1.htm">技术指南</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/stl/1.htm">stl</a>
                        <div>摘要本文深入探讨了AVL树(自平衡二叉搜索树)的概念、特点以及实现细节。我们首先介绍了AVL树的基本原理,并详细分析了其四种旋转操作,包括左旋、右旋、左右双旋和右左双旋,阐述了它们在保持树平衡中的重要作用。接着,本文从头到尾详细描述了AVL树的插入、删除和查找操作,配合完整的代码实现和详尽的注释,使读者能够全面理解这些操作的执行过程。此外,我们还提供了AVL树的遍历方法,包括中序、前序和后序遍历,</div>
                    </li>
                    <li><a href="/article/1835432854327226368.htm"
                           title="2024春节微信红包封面序列号大全一览" target="_blank">2024春节微信红包封面序列号大全一览</a>
                        <span class="text-muted">帮忙赚赏金</span>

                        <div>2024微信红包封面序列号哪里领取红包封面领取微信搜索公众号:【艺间封面】千万红包封面等你领取2024微信红包封面免费序列号如何设置微信红包封面?1.打开微信,点击好友选择红包。2.单击红包封面。3.单击“添加红包封面”。4.输入接收序列号。来一波免费的微信红包封面序列号微信红包封面序列号红包封面领取微信搜索公众号:艺间封面千万红包封面等你领取微信红包封面序列号kGnkrbw5a7N微信红包封面序</div>
                    </li>
                    <li><a href="/article/1835432213538238464.htm"
                           title="天猫返利网哪个最好?天猫返利网站有哪些?" target="_blank">天猫返利网哪个最好?天猫返利网站有哪些?</a>
                        <span class="text-muted">优惠券高省</span>

                        <div>关于哪个返利网站好用,今天汐儿给大家介绍以下十大网站,可以作为参考:1、高省网【高省APP】(邀请码:668666)全网佣金最高。手机应用商店搜索“高省”即可免费下载安装,填写高省邀请码:668666,直升2皇冠,享更高佣金及分红奖励。高省APP全网佣金最高,手机应用商店搜索“高省”即可下载,高省邀请码:668666,此码注册,直升2皇冠,佣金更高!送万元推广大礼包,教你如何1年做到百万团队。其实</div>
                    </li>
                    <li><a href="/article/1835429075590672384.htm"
                           title="粒子群优化 (PSO) 在三维正弦波函数中的应用" target="_blank">粒子群优化 (PSO) 在三维正弦波函数中的应用</a>
                        <span class="text-muted">subject625Ruben</span>
<a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/matlab/1.htm">matlab</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a>
                        <div>在这篇博客中,我们将展示如何使用粒子群优化(PSO)算法求解三维正弦波函数,并通过增加正弦波扰动,使优化过程更加复杂和有趣。本文将介绍目标函数的定义、PSO参数设置以及算法执行的详细过程,并展示搜索空间中的动态过程和收敛曲线。1.目标函数定义我们使用的目标函数是一个三维正弦波函数,定义如下:objectiveFunc=@(x)sin(sqrt(x(1).^2+x(2).^2))+0.5*sin(5</div>
                    </li>
                    <li><a href="/article/1835424412342513664.htm"
                           title="ChatGPT 高效学习套路揭秘:让知识获取事半功倍的秘诀" target="_blank">ChatGPT 高效学习套路揭秘:让知识获取事半功倍的秘诀</a>
                        <span class="text-muted">kkai人工智能</span>
<a class="tag" taget="_blank" href="/search/chatgpt/1.htm">chatgpt</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%AA%92%E4%BD%93/1.htm">媒体</a><a class="tag" taget="_blank" href="/search/ai/1.htm">ai</a>
                        <div>最近这段时间,AI热潮因ChatGPT的火爆再次掀起。如今,网上大部分内容都在调侃AI,但很少有人探讨如何正经使用ChatGPT做事情。作为一名靠搜索引擎和GitHub自学编程的开发者,第一次和ChatGPT深度交流后,我就确信:ChatGPT能够极大提高程序员学习新技术的效率。使用ChatGPT一个月后,我越发感受到它的颠覆性。因此,我想从工作和学习的角度,分享它的优势及我的一些使用技巧,而非娱</div>
                    </li>
                    <li><a href="/article/1835419492046434304.htm"
                           title="如何利用大数据与AI技术革新相亲交友体验" target="_blank">如何利用大数据与AI技术革新相亲交友体验</a>
                        <span class="text-muted">h17711347205</span>
<a class="tag" taget="_blank" href="/search/%E5%9B%9E%E5%BD%92%E7%AE%97%E6%B3%95/1.htm">回归算法</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/%E7%B3%BB%E7%BB%9F%E6%9E%B6%E6%9E%84/1.htm">系统架构</a><a class="tag" taget="_blank" href="/search/%E4%BA%A4%E5%8F%8B/1.htm">交友</a><a class="tag" taget="_blank" href="/search/%E5%B0%8F%E7%A8%8B%E5%BA%8F/1.htm">小程序</a>
                        <div>在数字化时代,大数据和人工智能(AI)技术正逐渐革新相亲交友体验,为寻找爱情的过程带来前所未有的变革(编辑h17711347205)。通过精准分析和智能匹配,这些技术能够极大地提高相亲交友系统的效率和用户体验。大数据的力量大数据技术能够收集和分析用户的行为模式、偏好和互动数据,为相亲交友系统提供丰富的信息资源。通过分析用户的搜索历史、浏览记录和点击行为,系统能够深入了解用户的兴趣和需求,从而提供更</div>
                    </li>
                    <li><a href="/article/1835404117007233024.htm"
                           title="HarmonyOS开发实战( Beta5.0)搜索框热搜词自动切换" target="_blank">HarmonyOS开发实战( Beta5.0)搜索框热搜词自动切换</a>
                        <span class="text-muted">让开,我要吃人了</span>
<a class="tag" taget="_blank" href="/search/OpenHarmony/1.htm">OpenHarmony</a><a class="tag" taget="_blank" href="/search/HarmonyOS/1.htm">HarmonyOS</a><a class="tag" taget="_blank" href="/search/%E9%B8%BF%E8%92%99%E5%BC%80%E5%8F%91/1.htm">鸿蒙开发</a><a class="tag" taget="_blank" href="/search/harmonyos/1.htm">harmonyos</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/1.htm">华为</a><a class="tag" taget="_blank" href="/search/%E9%B8%BF%E8%92%99/1.htm">鸿蒙</a><a class="tag" taget="_blank" href="/search/%E7%A7%BB%E5%8A%A8%E5%BC%80%E5%8F%91/1.htm">移动开发</a><a class="tag" taget="_blank" href="/search/%E9%B8%BF%E8%92%99%E7%B3%BB%E7%BB%9F/1.htm">鸿蒙系统</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>鸿蒙HarmonyOS开发往期必看:HarmonyOSNEXT应用开发性能实践总结最新版!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)介绍本示例介绍使用TextInput组件与Swiper组件实现搜索框内热搜词自动切换。效果图预览使用说明页面顶部搜索框内热搜词条自动切换,编辑搜索框时自动隐藏。实现思路使用TextInput实现搜索框TextInput({te</div>
                    </li>
                    <li><a href="/article/1835392013772615680.htm"
                           title="leetcode刷题day19|二叉树Part07(235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点)" target="_blank">leetcode刷题day19|二叉树Part07(235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点)</a>
                        <span class="text-muted">小冉在学习</span>
<a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a>
                        <div>235.二叉搜索树的最近公共祖先思路:二叉搜索树首先考虑中序遍历。根据二叉搜索树的特性,如果p,q分别在中间节点的左右两边,该中间节点一定是最近公共祖先,如果在同一侧,则递归这一侧即可。递归三部曲:1、传入参数:根节点,p,q,返回节点。2、终止条件:因为p,q一定存在,所以不会遍历到树的最底层,因此可以不写终止条件3、递归逻辑:如果p,q均小于root的值,递归调用左子树;如果p,q均大于roo</div>
                    </li>
                    <li><a href="/article/1835385331923382272.htm"
                           title="【大模型应用开发 动手做AI Agent】第一轮行动:工具执行搜索" target="_blank">【大模型应用开发 动手做AI Agent】第一轮行动:工具执行搜索</a>
                        <span class="text-muted">AI大模型应用之禅</span>
<a class="tag" taget="_blank" href="/search/%E8%AE%A1%E7%AE%97%E7%A7%91%E5%AD%A6/1.htm">计算科学</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E8%AE%A1%E7%AE%97/1.htm">神经计算</a><a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C/1.htm">神经网络</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E5%9E%8B%E8%AF%AD%E8%A8%80%E6%A8%A1%E5%9E%8B/1.htm">大型语言模型</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/AGI/1.htm">AGI</a><a class="tag" taget="_blank" href="/search/LLM/1.htm">LLM</a><a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1/1.htm">架构设计</a><a class="tag" taget="_blank" href="/search/Agent/1.htm">Agent</a><a class="tag" taget="_blank" href="/search/RPA/1.htm">RPA</a>
                        <div>【大模型应用开发动手做AIAgent】第一轮行动:工具执行搜索作者:禅与计算机程序设计艺术/ZenandtheArtofComputerProgramming1.背景介绍1.1问题的由来随着人工智能技术的飞速发展,大模型应用开发已经成为当下热门的研究方向。AIAgent作为人工智能领域的一个重要分支,旨在模拟人类智能行为,实现智能决策和自主行动。在AIAgent的构建过程中,工具执行搜索是至关重要</div>
                    </li>
                    <li><a href="/article/1835383919906746368.htm"
                           title="高性能javascript--算法和流程控制" target="_blank">高性能javascript--算法和流程控制</a>
                        <span class="text-muted">海淀萌狗</span>

                        <div>-for,while和do-while性能相当-避免使用for-in循环,==除非遍历一个属性量未知的对象==es5:for-in遍历的对象便不局限于数组,还可以遍历对象。原因:for-in每次迭代操作会同时搜索实例或者原型属性,for-in循环的每次迭代都会产生更多开销,因此要比其他循环类型慢,一般速度为其他类型循环的1/7。因此,除非明确需要迭代一个属性数量未知的对象,否则应避免使用for-i</div>
                    </li>
                    <li><a href="/article/1835375369167925248.htm"
                           title="阿里巴巴商品搜索API返回值实战解析" target="_blank">阿里巴巴商品搜索API返回值实战解析</a>
                        <span class="text-muted">weixin_43841111</span>
<a class="tag" taget="_blank" href="/search/api/1.htm">api</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>在解析阿里巴巴中国站商品搜索API返回值并进行实战时,可以从以下几个方面入手:一、了解API返回值的结构基本信息返回值通常包含商品的标题、价格、库存、图片链接等基本信息。这些信息对于了解商品的概况非常重要。例如,商品标题可以让你快速了解商品的名称和特点,价格信息可以帮助你进行价格比较和成本核算。详细描述可能包括商品的详细描述、规格参数、使用方法等。这些信息对于深入了解商品的特性和功能非常有帮助。比</div>
                    </li>
                    <li><a href="/article/1835373746014220288.htm"
                           title="果冻宝盒官方app邀请码有哪些一览(附邀请码填写指南)省钱又开心!" target="_blank">果冻宝盒官方app邀请码有哪些一览(附邀请码填写指南)省钱又开心!</a>
                        <span class="text-muted">小小编007</span>

                        <div>果冻宝盒是一款备受瞩目的社交电商软件,其独特的邀请机制和丰富的奖励制度吸引了大量用户。在使用果冻宝盒的过程中,填写正确的邀请码是获取奖励的重要步骤之一。本文将为您详细介绍果冻宝盒官方app的邀请码有哪些,以及如何正确填写邀请码,帮助您更好地参与果冻宝盒的社交电商生态。果冻宝盒直升金牌总裁(最高返利)注册教程:1各大应用市场搜索【果冻宝盒】并下载安装2注册果冻宝盒,根据提示填写邀请码:2233773</div>
                    </li>
                    <li><a href="/article/1835364965431734272.htm"
                           title="2022-04-25" target="_blank">2022-04-25</a>
                        <span class="text-muted">L是木子李呢</span>

                        <div>上门维修APP开发应具备哪些功能随着移动互联网的不断发展,上门维修在我们生活中已经是非常普遍的存在了,为了给用户更方便的找到上门维修的渠道,上门维修APP应运而生,那么上门维修APP开发应具备哪些功能呢?1、维修门店搜索为了更好地方便用户省时省力,上门维修APP会依据用户定位信息搜索线下实体店,促使用户更好的找到线下维修店面,省时又省力。2、维修服务分类包括管道洁具维修、强电弱电维修、木工维修、粉</div>
                    </li>
                    <li><a href="/article/1835333267952332800.htm"
                           title="网站推广爬虫" target="_blank">网站推广爬虫</a>
                        <span class="text-muted">Bearjumpingcandy</span>
<a class="tag" taget="_blank" href="/search/%E7%88%AC%E8%99%AB/1.htm">爬虫</a>
                        <div>网站推广爬虫是一种用于升网站曝光度和推广效果的工具。它通过自动化地访问和收集网站信息,从而实现对目标网站的广告、关键词、排名等数据进行分析和优化。以下是网站推广爬虫的一些介绍:数据收集:网站推广爬虫可以自动访问目标网站,并收集相关的数据,如网站流量、关键词排名、竞争对手信息等。这些数据可以帮助网站推广人员了解网站的现状和竞争环境,从而制定相应的推广策略。关键词优化:通过分析搜索引擎的关键词排名情况</div>
                    </li>
                    <li><a href="/article/1835319743318421504.htm"
                           title="【美食分享】油炸牛奶" target="_blank">【美食分享】油炸牛奶</a>
                        <span class="text-muted">吴老师教语文</span>

                        <div>一直宅在家里,闺女感觉很无聊,又不想学习,干嘛呢?突发奇想:做一道菜!啥菜呢?通过多方搜索,发现有一道菜看起来比较诱人:油炸牛奶。说做就做,这个喜欢拖延的娃,居然这次没有拖延。一个下午的忙碌,居然还真的做出了一道色香味俱全的菜肴。不信,晒图为证:这道菜,看着就很诱人,外焦里嫩。轻轻夹起一块,咬上一口,嫩嫩的,香香的,糯糯的,滑滑的,哇,唇齿留香,美味无比!闺女盯着我,期待地眼光看着我:“咋样?好吃</div>
                    </li>
                    <li><a href="/article/1835316433458917376.htm"
                           title="一部手机就能操作的10种赚钱方式,看看哪种适合你?" target="_blank">一部手机就能操作的10种赚钱方式,看看哪种适合你?</a>
                        <span class="text-muted">氧惠全网优惠</span>

                        <div>手机已经成为了我们生活中不可或缺的一部分,拿着手机刷分享赚钱已经成为了不少人的日常。今天,我想和大家分享一下手机赚钱的10种好方法。京东密令红包:最爱领红包828红包多多148今天给大家分享我长期在做的副业,也在这里赚到人生第3桶金!氧惠APP佣金高,资质靠谱,各大应用市场均可搜索使用。【氧惠】氧惠app是杭州长孚科技有限公司旗下一款新开发电商导购应用,为用户打造一个集成电商购物优惠佣金平台,公司</div>
                    </li>
                    <li><a href="/article/1835303427685576704.htm"
                           title="UI 自动化的页面对象管理神器 PO-Manager" target="_blank">UI 自动化的页面对象管理神器 PO-Manager</a>
                        <span class="text-muted">TesterHome</span>

                        <div>原文由alex发表于TesterHome社区网站,点击原文链接可于作者直接交流。做UI自动化的同学都知道,UI自动化一个难点就是页面元素的变化,让自动化维护成为一个痛点。在此,为了减轻这个痛点,我在基于Page-Object模式的基础上开发了页面对象维护的工具。该工具为vscode的一个插件,可以通过vscode插件市场搜索PO-Manager来下载安装本文中的页面对象库文件基于json.一个元素</div>
                    </li>
                    <li><a href="/article/1835296695089459200.htm"
                           title="亚马逊真的可以赚钱吗?亚马逊怎么做才能赚钱?" target="_blank">亚马逊真的可以赚钱吗?亚马逊怎么做才能赚钱?</a>
                        <span class="text-muted">古楼</span>

                        <div>1、代购:近年来,随着移动支付和国际物流的发展,代购行业不再像以前那样火爆,但依旧有着不错的利润空间,大家可以兼职亚马逊代购,获得手续费,汇率差价等等,是可以赚到钱的。2、跨境电商:所谓的亚马逊跨境电商,就是通过通过亚马逊跨境平台,把中国的货物卖到全球去,虽然在国内,亚马逊的流量不如京东、淘宝、拼多多,但在国外亚马逊的流量是很高的,其市场空间庞大。一、注册店铺网页搜索“亚马逊全球开店”进入官网。找</div>
                    </li>
                    <li><a href="/article/1835296440692338688.htm"
                           title="大家在哪里买高仿包包,推荐6个最新渠道" target="_blank">大家在哪里买高仿包包,推荐6个最新渠道</a>
                        <span class="text-muted">腕表鞋屋</span>

                        <div>大家在哪里买高仿包包,推荐6个最新渠道在如今的社会中,有许多人喜欢购买高仿包包。虽然真正的奢侈品价格昂贵,但是高仿包包的外观和品质却能够满足大多数人的需求。那么,大家想知道在哪里买高仿包包吗?下面就为大家推荐6个最新渠道。微信:97870758(下单赠送精美礼品)第一个渠道是线上购物平台。如今,互联网的发展让我们可以方便地在各大电商平台上搜索并购买高仿包包。一些知名的电商平台如淘宝、京东等都有很多</div>
                    </li>
                                <li><a href="/article/55.htm"
                                       title="多线程编程之卫生间" target="_blank">多线程编程之卫生间</a>
                                    <span class="text-muted">周凡杨</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%B9%B6%E5%8F%91/1.htm">并发</a><a class="tag" taget="_blank" href="/search/%E5%8D%AB%E7%94%9F%E9%97%B4/1.htm">卫生间</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a><a class="tag" taget="_blank" href="/search/%E5%8E%95%E6%89%80/1.htm">厕所</a>
                                    <div>如大家所知,火车上车厢的卫生间很小,每次只能容纳一个人,一个车厢只有一个卫生间,这个卫生间会被多个人同时使用,在实际使用时,当一个人进入卫生间时则会把卫生间锁上,等出来时打开门,下一个人进去把门锁上,如果有一个人在卫生间内部则别人的人发现门是锁的则只能在外面等待。问题分析:首先问题中有两个实体,一个是人,一个是厕所,所以设计程序时就可以设计两个类。人是多数的,厕所只有一个(暂且模拟的是一个车厢)。</div>
                                </li>
                                <li><a href="/article/182.htm"
                                       title="How to Install GUI to Centos Minimal" target="_blank">How to Install GUI to Centos Minimal</a>
                                    <span class="text-muted">sunjing</span>
<a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/Install/1.htm">Install</a><a class="tag" taget="_blank" href="/search/Desktop/1.htm">Desktop</a><a class="tag" taget="_blank" href="/search/GUI/1.htm">GUI</a>
                                    <div>http://www.namhuy.net/475/how-to-install-gui-to-centos-minimal.html 
  
I have centos 6.3 minimal running as web server. I’m looking to install gui to my server to vnc to my server. You can insta</div>
                                </li>
                                <li><a href="/article/309.htm"
                                       title="Shell 函数" target="_blank">Shell 函数</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/shell/1.htm">shell</a><a class="tag" taget="_blank" href="/search/%E5%87%BD%E6%95%B0/1.htm">函数</a>
                                    <div>Shell 函数 
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。 
shell中函数的定义格式如下: 
[function] funname [()]{

    action;
  
     [return int;]

} 
说明: 
 
 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。 
 2、参数返回</div>
                                </li>
                                <li><a href="/article/436.htm"
                                       title="Linux服务器新手操作之一" target="_blank">Linux服务器新手操作之一</a>
                                    <span class="text-muted">周凡杨</span>
<a class="tag" taget="_blank" href="/search/Linux+%E7%AE%80%E5%8D%95+%E6%93%8D%E4%BD%9C/1.htm">Linux 简单 操作</a>
                                    <div>1.whoami 
     当一个用户登录Linux系统之后,也许他想知道自己是发哪个用户登录的。 
     此时可以使用whoami命令。 
     [ecuser@HA5-DZ05 ~]$ whoami 
      e</div>
                                </li>
                                <li><a href="/article/563.htm"
                                       title="浅谈Socket通信(一)" target="_blank">浅谈Socket通信(一)</a>
                                    <span class="text-muted">朱辉辉33</span>
<a class="tag" taget="_blank" href="/search/socket/1.htm">socket</a>
                                    <div>在java中ServerSocket用于服务器端,用来监听端口。通过服务器监听,客户端发送请求,双方建立链接后才能通信。当服务器和客户端建立链接后,两边都会产生一个Socket实例,我们可以通过操作Socket来建立通信。 
   首先我建立一个ServerSocket对象。当然要导入java.net.ServerSocket包 
   ServerSock</div>
                                </li>
                                <li><a href="/article/690.htm"
                                       title="关于框架的简单认识" target="_blank">关于框架的简单认识</a>
                                    <span class="text-muted">西蜀石兰</span>
<a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a>
                                    <div>入职两个月多,依然是一个不会写代码的小白,每天的工作就是看代码,写wiki。 
前端接触CSS、HTML、JS等语言,一直在用的CS模型,自然免不了数据库的链接及使用,真心涉及框架,项目中用到的BootStrap算一个吧,哦,JQuery只能算半个框架吧,我更觉得它是另外一种语言。 
后台一直是纯Java代码,涉及的框架是Quzrtz和log4j。 
 
都说学前端的要知道三大框架,目前node.</div>
                                </li>
                                <li><a href="/article/817.htm"
                                       title="You have an error in your SQL syntax; check the manual that corresponds to your" target="_blank">You have an error in your SQL syntax; check the manual that corresponds to your</a>
                                    <span class="text-muted">林鹤霄</span>

                                    <div>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'option,changed_ids  ) values('0ac91f167f754c8cbac00e9e3dc372</div>
                                </li>
                                <li><a href="/article/944.htm"
                                       title="MySQL5.6的my.ini配置" target="_blank">MySQL5.6的my.ini配置</a>
                                    <span class="text-muted">aigo</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>注意:以下配置的服务器硬件是:8核16G内存  
  
[client] 
  
port=3306 
  
[mysql] 
  
default-character-set=utf8 
  
  
[mysqld] 
  
port=3306 
  
basedir=D:/mysql-5.6.21-win</div>
                                </li>
                                <li><a href="/article/1071.htm"
                                       title="mysql 全文模糊查找 便捷解决方案" target="_blank">mysql 全文模糊查找 便捷解决方案</a>
                                    <span class="text-muted">alxw4616</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>mysql 全文模糊查找 便捷解决方案 
2013/6/14 by 半仙 alxw4616@Msn.com 
 
目的: 项目需求实现模糊查找. 
原则: 查询不能超过 1秒. 
 
问题: 目标表中有超过1千万条记录. 使用like '%str%' 进行模糊查询无法达到性能需求. 
解决方案: 使用mysql全文索引. 
 1.全文索引 : MySQL支持全文索引和搜索功能。MySQL中的全文索</div>
                                </li>
                                <li><a href="/article/1198.htm"
                                       title="自定义数据结构 链表(单项 ,双向,环形)" target="_blank">自定义数据结构 链表(单项 ,双向,环形)</a>
                                    <span class="text-muted">百合不是茶</span>
<a class="tag" taget="_blank" href="/search/%E5%8D%95%E9%A1%B9%E9%93%BE%E8%A1%A8/1.htm">单项链表</a><a class="tag" taget="_blank" href="/search/%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8/1.htm">双向链表</a>
                                    <div>  
   链表与动态数组的实现方式差不多,    数组适合快速删除某个元素    链表则可以快速的保存数组并且可以是不连续的 
  
    
单项链表;数据从第一个指向最后一个 
  
实现代码: 
  
     
//定义动态链表
clas</div>
                                </li>
                                <li><a href="/article/1325.htm"
                                       title="threadLocal实例" target="_blank">threadLocal实例</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a><a class="tag" taget="_blank" href="/search/java%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">java多线程</a><a class="tag" taget="_blank" href="/search/threadLocal/1.htm">threadLocal</a>
                                    <div>实例1: 
package com.bijian.thread;

public class MyThread extends Thread {

	private static ThreadLocal tl = new ThreadLocal() {
		protected synchronized Object initialValue() {
			return new Inte</div>
                                </li>
                                <li><a href="/article/1452.htm"
                                       title="activemq安全设置—设置admin的用户名和密码" target="_blank">activemq安全设置—设置admin的用户名和密码</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/activemq/1.htm">activemq</a>
                                    <div>        ActiveMQ使用的是jetty服务器, 打开conf/jetty.xml文件,找到 
<bean id="adminSecurityConstraint" class="org.eclipse.jetty.util.security.Constraint">
        <p</div>
                                </li>
                                <li><a href="/article/1579.htm"
                                       title="【Java范型一】Java范型详解之范型集合和自定义范型类" target="_blank">【Java范型一】Java范型详解之范型集合和自定义范型类</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>本文详细介绍Java的范型,写一篇关于范型的博客原因有两个,前几天要写个范型方法(返回值根据传入的类型而定),竟然想了半天,最后还是从网上找了个范型方法的写法;再者,前一段时间在看Gson, Gson这个JSON包的精华就在于对范型的优雅简单的处理,看它的源代码就比较迷糊,只其然不知其所以然。所以,还是花点时间系统的整理总结下范型吧。 
  范型内容 
 
 范型集合类 
 范型类 
 </div>
                                </li>
                                <li><a href="/article/1706.htm"
                                       title="【HBase十二】HFile存储的是一个列族的数据" target="_blank">【HBase十二】HFile存储的是一个列族的数据</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/hbase/1.htm">hbase</a>
                                    <div>在HBase中,每个HFile存储的是一个表中一个列族的数据,也就是说,当一个表中有多个列簇时,针对每个列簇插入数据,最后产生的数据是多个HFile,每个对应一个列族,通过如下操作验证 
  
1. 建立一个有两个列族的表 
  
create 'members','colfam1','colfam2' 
  
2. 在members表中的colfam1中插入50*5</div>
                                </li>
                                <li><a href="/article/1833.htm"
                                       title="Nginx 官方一个配置实例" target="_blank">Nginx 官方一个配置实例</a>
                                    <span class="text-muted">ronin47</span>
<a class="tag" taget="_blank" href="/search/nginx+%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B/1.htm">nginx 配置实例</a>
                                    <div>user       www www;
worker_processes  5;
error_log  logs/error.log;
pid        logs/nginx.pid;
worker_rlimit_nofile 8192;

events {
  worker_connections  4096;}

http {
  include    conf/mim</div>
                                </li>
                                <li><a href="/article/1960.htm"
                                       title="java-15.输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 用递归和循环" target="_blank">java-15.输入一颗二元查找树,将该树转换为它的镜像, 即在转换后的二元查找树中,左子树的结点都大于右子树的结点。 用递归和循环</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>
//use recursion
	public static void mirrorHelp1(Node node){
		if(node==null)return;
		swapChild(node);
		mirrorHelp1(node.getLeft());
		mirrorHelp1(node.getRight());
	}
	//use no recursion bu</div>
                                </li>
                                <li><a href="/article/2087.htm"
                                       title="返回null还是empty" target="_blank">返回null还是empty</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/apache/1.htm">apache</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a>
                                    <div>第一个问题,函数是应当返回null还是长度为0的数组(或集合)? 
第二个问题,函数输入参数不当时,是异常还是返回null? 
 
先看第一个问题 
 
有两个约定我觉得应当遵守: 
 
1.返回零长度的数组或集合而不是null(详见《Effective Java》) 
 
理由就是,如果返回empty,就可以少了很多not-null判断: 
 

List<Person> list</div>
                                </li>
                                <li><a href="/article/2214.htm"
                                       title="[科技与项目]工作流厂商的战略机遇期" target="_blank">[科技与项目]工作流厂商的战略机遇期</a>
                                    <span class="text-muted">comsci</span>
<a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C%E6%B5%81/1.htm">工作流</a>
                                    <div> 
 
      在新的战略平衡形成之前,这里有一个短暂的战略机遇期,只有大概最短6年,最长14年的时间,这段时间就好像我们森林里面的小动物,在秋天中,必须抓紧一切时间存储坚果一样,否则无法熬过漫长的冬季。。。。 
 
 
        在微软,甲骨文,谷歌,IBM,SONY</div>
                                </li>
                                <li><a href="/article/2341.htm"
                                       title="过度设计-举例" target="_blank">过度设计-举例</a>
                                    <span class="text-muted">cuityang</span>
<a class="tag" taget="_blank" href="/search/%E8%BF%87%E5%BA%A6%E8%AE%BE%E8%AE%A1/1.htm">过度设计</a>
                                    <div>过度设计,需要更多设计时间和测试成本,如无必要,还是尽量简洁一些好。 
未来的事情,比如 访问量,比如数据库的容量,比如是否需要改成分布式  都是无法预料的 
 
再举一个例子,对闰年的判断逻辑: 
  1、 if($Year%4==0) return True; else return Fasle; 
  2、if (   ($Year%4==0  &am</div>
                                </li>
                                <li><a href="/article/2468.htm"
                                       title="java进阶,《Java性能优化权威指南》试读" target="_blank">java进阶,《Java性能优化权威指南》试读</a>
                                    <span class="text-muted">darkblue086</span>
<a class="tag" taget="_blank" href="/search/java%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96/1.htm">java性能优化</a>
                                    <div>记得当年随意读了微软出版社的.NET 2.0应用程序调试,才发现调试器如此强大,应用程序开发调试其实真的简单了很多,不仅仅是因为里面介绍了很多调试器工具的使用,更是因为里面寻找问题并重现问题的思想让我震撼,时隔多年,Java已经如日中天,成为许多大型企业应用的首选,而今天,这本《Java性能优化权威指南》让我再次找到了这种感觉,从不经意的开发过程让我刮目相看,原来性能调优不是简单地看看热点在哪里,</div>
                                </li>
                                <li><a href="/article/2595.htm"
                                       title="网络学习笔记初识OSI七层模型与TCP协议" target="_blank">网络学习笔记初识OSI七层模型与TCP协议</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">学习笔记</a>
                                    <div>   协议:在计算机网络中通信各方面所达成的、共同遵守和执行的一系列约定     计算机网络的体系结构:计算机网络的层次结构和各层协议的集合。     两类服务:     面向连接的服务通信双方在通信之前先建立某种状态,并在通信过程中维持这种状态的变化,同时为服务对象预先分配一定的资源。这种服务叫做面向连接的服务。     面向无连接的服务通信双方在通信前后不建立和维持状态,不为服务对象</div>
                                </li>
                                <li><a href="/article/2722.htm"
                                       title="mac中用命令行运行mysql" target="_blank">mac中用命令行运行mysql</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/mac/1.htm">mac</a>
                                    <div>参考这篇博客:http://www.cnblogs.com/macro-cheng/archive/2011/10/25/mysql-001.html  感觉workbench不好用(有点先入为主了)。 
1,安装mysql 
在mysql的官方网站下载 mysql 5.5.23 http://www.mysql.com/downloads/mysql/,根据我的机器的配置情况选择了64</div>
                                </li>
                                <li><a href="/article/2849.htm"
                                       title="MongDB查询(1)——基本查询[五]" target="_blank">MongDB查询(1)——基本查询[五]</a>
                                    <span class="text-muted">eksliang</span>
<a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a><a class="tag" taget="_blank" href="/search/mongodb+%E6%9F%A5%E8%AF%A2/1.htm">mongodb 查询</a><a class="tag" taget="_blank" href="/search/mongodb+find/1.htm">mongodb find</a>
                                    <div>MongDB查询 
转载请出自出处:http://eksliang.iteye.com/blog/2174452 一、find简介 
MongoDB中使用find来进行查询。 
API:如下 
function ( query , fields , limit , skip, batchSize, options ){.....} 
 参数含义: 
 
 query:查询参数 
 fie</div>
                                </li>
                                <li><a href="/article/2976.htm"
                                       title="base64,加密解密 经融加密,对接" target="_blank">base64,加密解密 经融加密,对接</a>
                                    <span class="text-muted">y806839048</span>
<a class="tag" taget="_blank" href="/search/%E7%BB%8F%E8%9E%8D%E5%8A%A0%E5%AF%86/1.htm">经融加密</a><a class="tag" taget="_blank" href="/search/%E5%AF%B9%E6%8E%A5/1.htm">对接</a>
                                    <div>String data0 = new String(Base64.encode(bo.getPaymentResult().getBytes(("GBK")))); 
 String data1 = new String(Base64.decode(data0.toCharArray()),"GBK"); 
 
// 注意编码格式,注意用于加密,解密的要是同</div>
                                </li>
                                <li><a href="/article/3103.htm"
                                       title="JavaWeb之JSP概述" target="_blank">JavaWeb之JSP概述</a>
                                    <span class="text-muted">ihuning</span>
<a class="tag" taget="_blank" href="/search/javaweb/1.htm">javaweb</a>
                                    <div>  
什么是JSP?为什么使用JSP? 
JSP表示Java Server Page,即嵌有Java代码的HTML页面。使用JSP是因为在HTML中嵌入Java代码比在Java代码中拼接字符串更容易、更方便和更高效。 
  
JSP起源  
  
在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。  
如果使用Servl</div>
                                </li>
                                <li><a href="/article/3230.htm"
                                       title="apple watch 指南" target="_blank">apple watch 指南</a>
                                    <span class="text-muted">啸笑天</span>
<a class="tag" taget="_blank" href="/search/apple/1.htm">apple</a>
                                    <div>1. 文档 
 
  WatchKit Programming Guide(中译在线版 By @CocoaChina)    译文 译者 原文   概览 - 开始为 Apple Watch 进行开发 @星夜暮晨 Overview - Developing for Apple Watch   概览 - 配置 Xcode 项目 - Overview - Configuring Yo</div>
                                </li>
                                <li><a href="/article/3357.htm"
                                       title="java经典的基础题目" target="_blank">java经典的基础题目</a>
                                    <span class="text-muted">macroli</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a>
                                    <div>1.列举出 10个JAVA语言的优势 a:免费,开源,跨平台(平台独立性),简单易用,功能完善,面向对象,健壮性,多线程,结构中立,企业应用的成熟平台, 无线应用 2.列举出JAVA中10个面向对象编程的术语 a:包,类,接口,对象,属性,方法,构造器,继承,封装,多态,抽象,范型 3.列举出JAVA中6个比较常用的包 Java.lang;java.util;java.io;java.sql;ja</div>
                                </li>
                                <li><a href="/article/3484.htm"
                                       title="你所不知道神奇的js replace正则表达式" target="_blank">你所不知道神奇的js replace正则表达式</a>
                                    <span class="text-muted">qiaolevip</span>
<a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E7%BA%B5%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">纵观千象</a><a class="tag" taget="_blank" href="/search/regex/1.htm">regex</a>
                                    <div>var v = 'C9CFBAA3CAD0';
console.log(v);
var arr = v.split('');
for (var i = 0; i < arr.length; i ++) {
  if (i % 2 == 0) arr[i] = '%' + arr[i];
}
console.log(arr.join(''));

console.log(v.r</div>
                                </li>
                                <li><a href="/article/3611.htm"
                                       title="[一起学Hive]之十五-分析Hive表和分区的统计信息(Statistics)" target="_blank">[一起学Hive]之十五-分析Hive表和分区的统计信息(Statistics)</a>
                                    <span class="text-muted">superlxw1234</span>
<a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a><a class="tag" taget="_blank" href="/search/hive%E5%88%86%E6%9E%90%E8%A1%A8/1.htm">hive分析表</a><a class="tag" taget="_blank" href="/search/hive%E7%BB%9F%E8%AE%A1%E4%BF%A1%E6%81%AF/1.htm">hive统计信息</a><a class="tag" taget="_blank" href="/search/hive+Statistics/1.htm">hive Statistics</a>
                                    <div>关键字:Hive统计信息、分析Hive表、Hive Statistics 
  
类似于Oracle的分析表,Hive中也提供了分析表和分区的功能,通过自动和手动分析Hive表,将Hive表的一些统计信息存储到元数据中。 
  
表和分区的统计信息主要包括:行数、文件数、原始数据大小、所占存储大小、最后一次操作时间等; 
  14.1 新表的统计信息 
对于一个新创建</div>
                                </li>
                                <li><a href="/article/3738.htm"
                                       title="Spring Boot 1.2.5 发布" target="_blank">Spring Boot 1.2.5 发布</a>
                                    <span class="text-muted">wiselyman</span>
<a class="tag" taget="_blank" href="/search/spring+boot/1.htm">spring boot</a>
                                    <div>  
  
Spring Boot 1.2.5已在7月2日发布,现在可以从spring的maven库和maven中心库下载。 
  
这个版本是一个维护的发布版,主要是一些修复以及将Spring的依赖提升至4.1.7(包含重要的安全修复)。 
  
官方建议所有的Spring Boot用户升级这个版本。 
  
项目首页 | 源</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>