pLdZB9oD]C
9B)<7JJX!J
HuI?kLfj\
第一部分:A*算法简介 9cqq"-$G`
写这篇文章的初衷是应一个网友的要求,当然我也发现现在有关人工智能的中文站点实在太少,我在这里 抛砖引玉,希望大家都来热心的参与。 GbB:K2
还是说正题,我先拿A*算法开刀,是因为A*在游戏中有它很典型的用法,是人工智能在游戏中的代表。 ~bD'QMk
A*算法在人工智能中是一种典型的启发式搜索算法,为了说清楚A*算法,我看还是先说说何谓启发式算法。 bC
h
5 (cgHr"
一、何谓启发式搜索算法: 'eYM;\%('
=O
o4O CF2
在说它之前先提提状态空间搜索。状态空间搜索,如果按专业点的说法就是将问题求解过程表现为从 初始状态到目标状态寻找这个路径的过程。通俗点说,就是在解一个问题时,找到一条解题的过程可以从 求解的开始到问题的结果(好象并不通俗哦)。由于求解问题的过程中分枝有很多,主要是求解过程中求 解条件的不确定性,不完备性造成的,使得求解的路径很多这就构成了一个图,我们说这个图就是状态空 间。问题的求解实际上就是在这个图中找到一条路径可以从开始到结果。这个寻找的过程就是状态空间搜 索。 c'}dsq\
`JAM]qB"
常用的状态空间搜索有深度优先和广度优先。广度优先是从初始状态一层一层向下找,直到找到目标 为止。深度优先是按照一定的顺序前查找完一个分支,再查找另一个分支,以至找到目标为止。这两种算 法在数据结构书中都有描述,可以参看这些书得到更详细的解释。 d:!A`sk7
MhL>6
rn
前面说的广度和深度优先搜索有一个很大的缺陷就是他们都是在一个给定的状态空间中穷举。这在状 态空间不大的情况下是很合适的算法,可是当状态空间十分大,且不预测的情况下就不可取了。他的效率 实在太低,甚至不可完成。在这里就要用到启发式搜索了。 ym*oCfu=
%] #XIr
启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置 进行搜索直到目标。这样可以省略大量无畏的搜索路径,提到了效率。在启发式搜索中,对位置的估价是 十分重要的。采用了不同的估价可以有不同的效果。我们先看看估价是如何表示的。 |r<#>~*
o>j
M4sk$
启发中的估价是用估价函数表示的,如: &cf(}
= P@j*ix
f(n) = g(n) + h(n) OzA'd\|
jnIf(a
其中f(n) 是节点n的估价函数,g(n)实在状态空间中从初始节点到n节点的实际代价,h(n)是从n到目 标节点最佳路径的估计代价。在这里主要是h(n)体现了搜索的启发信息,因为g(n)是已知的。如果说详细 点,g(n)代表了搜索的广度的优先趋势。但是当h(n) >> g(n)时,可以省略g(n),而提高效率。这些就深了, 不懂也不影响啦!我们继续看看何谓A*算法。 fq<JX5DER
k];NTALOG
二、初识A*算法: r
WULv
cnraNq1
启发式搜索其实有很多的算法,比如:局部择优搜索法、最好优先搜索法等等。当然A*也是。这些算法 都使用了启发函数,但在具体的选取最佳搜索节点时的策略不同。象局部择优搜索法,就是在搜索的过程中 选取“最佳节点”后舍弃其他的兄弟节点,父亲节点,而一直得搜索下去。这种搜索的结果很明显,由于舍 弃了其他的节点,可能也把最好的节点都舍弃了,因为求解的最佳节点只是在该阶段的最佳并不一定是全局 的最佳。最好优先就聪明多了,他在搜索时,便没有舍弃节点(除非该节点是死节点),在每一步的估价中 都把当前的节点和以前的节点的估价值比较得到一个“最佳的节点”。这样可以有效的防止“最佳节点”的 丢失。那么A*算法又是一种什么样的算法呢?其实A*算法也是一种最好优先的算法。只不过要加上一些约束 条件罢了。由于在一些问题求解时,我们希望能够求解出状态空间搜索的最短路径,也就是用最快的方法求 解问题,A*就是干这种事情的!我们先下个定义,如果一个估价函数可以找出最短的路径,我们称之为可采 纳性。A*算法是一个可采纳的最好优先算法。A*算法的估价函数克表示为: uA;vW\fHr
jxqKPMf>@%
f’(n) = g’(n) + h’(n) ~-2Gx
HO`
/C
这里,f’(n)是估价函数,g’(n)是起点到终点的最短路径值,h’(n)是n到目标的最断路经的启发值。由 于这个f’(n)其实是无法预先知道的,所以我们用前面的估价函数f(n)做近似。g(n)代替g’(n),但 g(n)>=g’(n) 才可(大多数情况下都是满足的,可以不用考虑),h(n)代替h’(n),但h(n)<=h’(n)才可(这一点特别的重 要)。可以证明应用这样的估价函数是可以找到最短路径的,也就是可采纳的。我们说应用这种估价函数的 最好优先算法就是A*算法。哈!你懂了吗?肯定没懂!接着看! "ph<V,lg
LTw.w:"J
举一个例子,其实广度优先算法就是A*算法的特例。其中g(n)是节点所在的层数,h(n)=0,这种h(n)肯 定小于h’(n),所以由前述可知广度优先算法是一种可采纳的。实际也是。当然它是一种最臭的A*算法。 <?FkwW\?
SIZZFihcYh
再说一个问题,就是有关h(n)启发函数的信息性。h(n)的信息性通俗点说其实就是在估计一个节点的值 时的约束条件,如果信息越多或约束条件越多则排除的节点就越多,估价函数越好或说这个算法越好。这就 是为什么广度优先算法的那么臭的原因了,谁叫它的h(n)=0,一点启发信息都没有。但在游戏开发中由于实 时性的问题,h(n)的信息越多,它的计算量就越大,耗费的时间就越多。就应该适当的减小h(n)的信息,即 减小约束条件。但算法的准确性就差了,这里就有一个平衡的问题。可难了,这就看你的了! *!MMl]gU?
_b"K,[0o
好了我的话也说得差不多了,我想你肯定是一头的雾水了,其实这是写给懂A*算法的同志看的。哈哈! 你还是找一本人工智能的书仔细看看吧!我这几百字是不足以将A*算法讲清楚的。只是起到抛砖引玉的作用 希望大家热情参与吗! )skz_a}]8
MqjdW
预知A*算法的应用,请看《深入A*算法》。 7q(A&
'.{_
7U
第二部分:深入A*算法———浅析A*算法在搜索最短路径中的应用 Q<>b3X>O
vYg>^!Q
一、前言 1ne3CA=
^X;p8uBo
在这里我将对A*算法的实际应用进行一定的探讨,并且举一个有关A*算法在最短路径搜索 的例子。值得注意的是这里并不对A*的基本的概念作介绍,如果你还对A*算法不清楚的话, 请看姊妹篇《初识A*算法》。 apgR[=Oy
N/78Ub
这里所举的例子是参考AMIT主页中的一个源程序,你可以在AMIT的站点上下载也可以在我 的站点上下载。你使用这个源程序时,应该遵守一定的公约。 CE
@[Z
DY\~O
二、A*算法的程序编写原理 GfV#^qi
e2yCWolmTS
我在《初识A*算法》中说过,A*算法是最好优先算法的一种。只是有一些约束条件而已。 我们先来看看最好优先算法是如何编写的吧。
`|2g&Vn
t:"3MiM=c
如图有如下的状态空间:(起始位置是A,目标位置是P,字母后的数字表示节点的估价值) sYbmL`{
ey6ujV7!
搜索过程中设置两个表:OPEN和CLOSED。OPEN表保存了所有已生成而未考察的节点,CLOSED 表中记录已访问过的节点。算法中有一步是根据估价函数重排OPEN表。这样循环中的每一 步只考虑OPEN表中状态最好的节点。具体搜索过程如下: nH<#MGBS
~=Q^]y,
1)初始状态: @nAl*#M*D
OPEN=[A5];CLOSED=[]; 0xY</S
2)估算A5,取得搜有子节点,并放入OPEN表中; p-r[M5;-^Q
OPEN=[B4,C4,D6];CLOSED=[A5] l0U23i
3)估算B4,取得搜有子节点,并放入OPEN表中; %>$Puy\U
OPEN=[C4,E5,F5,D6];CLOSED=[B4,A5]
[8~P
Pc^
4)估算C4;取得搜有子节点,并放入OPEN表中; 6bPl(.(3
OPEN=[H3,G4,E5,F5,D6];CLOSED=[C4,B4,A5] 4,>9N9.?9
5)估算H3,取得搜有子节点,并放入OPEN表中; '/)qI.
OPEN=[O2,P3,G4,E5,F5,D6];CLOSED=H3C4,B4,A5] =^Sx
Z Bn
6)估算O2,取得搜有子节点,并放入OPEN表中; ~GcWG4
OPEN=[P3,G4,E5,F5,D6];CLOSED=[O2,H3,C4,B4,A5] B%tWi
7)估算P3,已得到解; BNj_f
看了具体的过程,再看看伪程序吧。算法的伪程序如下: ^,#my<{
#f<
v%
Best_First_Search() *\(z
"B
{ Nke!!A}\|
Open = [起始节点]; Closed = []; 6i2%EC9
while ( Open表非空 ) 6JDaZh"=K
{ yIrJaS-
从Open中取得一个节点X,并从OPEN表中删除。 iaCV8`&q%
if (X是目标节点) ?3p7MjvZ
{ :8!RGtn
求得路径PATH;返回路径PATH; =E5bM_P<K
} w4vV#C4X
for (每一个X的子节点Y) Y}1c>5{bE
{ KWZhCS?[(
if( Y不在OPEN表和CLOSE表中 ) Aeb(b+=
{ IQRuqp KL
求Y的估价值;并将Y插入OPEN表中;//还没有排序 \gk.[={^P
} Aj)Q#Fd[
else F5Z,Jmi^M
if( Y在OPEN表中 ) u3C_Xz
{ l6ym <V(1p
if( Y的估价值小于OPEN表的估价值 ) =
/!lK&
更新OPEN表中的估价值; d_,5;M^k
} e
@Lxduq
else //Y在CLOSE表中 AJbCC
{ Lwr's'ao.
if( Y的估价值小于CLOSE表的估价值 ) .|Huzk+
{ h0'*)`;z
更新CLOSE表中的估价值; uiVNz8H
从CLOSE表中移出节点,并放入OPEN表中; :A8}x=K
} *n
CA6i
} Y%XF64)6
将X节点插入CLOSE表中; EtKq.<SJ
按照估价值将OPEN表中的节点排序; >}+{;d
}//end for wJy]Vyd
}//end while um.ZAS_kmc
}//end func ;W,* B.~
5/=$p:E>
啊!伪程序出来了,写一个源程序应该不是问题了,依葫芦画瓢就可以。A*算法的程序与此 是一样的,只要注意估价函数中的g(n)的h(n)约束条件就可以了。不清楚的可以看看《初识A*算法》。好了,我们可以进入另一个重要的话题,用A*算法实现最短路径的搜索。在此之 前你最好认真的理解前面的算法。不清楚可以找我。我的Email在文章尾。 9/k2zXY
:_8K8Sa
三、用A*算法实现最短路径的搜索 ;6G]~}>o
@t%da^-HS"
在游戏设计中,经常要涉及到最短路径的搜索,现在一个比较好的方法就是用A*算法进行设 计。他的好处我们就不用管了,反正就是好!^_* 7Qd4L.
C4mkt2Eb0a
^E70$yB^
注意下面所说的都是以 ClassAstar 这个程序为蓝本,你可以在这里下载这个程序。这个程 序是一个完整的工程。里面带了一个EXE文件。可以先看看。 \.i7(J]
j1_>>xB
先复习一下,A*算法的核心是估价函数f(n),它包括g(n)和h(n)两部分。g(n) 是已经走过的 代价,h(n)是n到目标的估计代价。在这个例子中g(n)表示在状态空间从起始节点到 n节点的 深度,h(n)表示n节点所在地图的位置到目标位置的直线距离。啊!一个是状态空间,一个是 实际的地图,不要搞错了。再详细点说,有一个物体A,在地图上的坐标是(xa,ya),A所要到 达的目标b的坐标是(xb,yb)。则开始搜索时,设置一个起始节点1,生成八个子节点2 - 9 因 为有八个方向。如图: 7X$CJ%6b
|
.jWz.c
仔细看看节点1、9、17的g(n)和h(n)是怎么计算的。现在应该知道了下面程序中的f(n)是如何 计算的吧。开始讲解源程序了。其实这个程序是一个很典型的教科书似的程序,也就是说只要 你看懂了上面的伪程序,这个程序是十分容易理解的。不过他和上面的伪程序有一些的不同, 我在后面会提出来。 $DDO9
Fp.eucRxP
先看搜索主函数: :` SIuu~@
,$6si
void AstarPathfinder::FindPath(int sx, int sy, int dx, int dy) 02]HwsvZ
{ %DttkrhL
NODE *Node, *BestNode; s)
\PY
int TileNumDest; R
~=c1bpdq
//得到目标位置,作判断用 3cJ'tRsp<
TileNumDest = TileNum(sx, sy); Yup#aeXY/
//生成Open和Closed表 ^@x&n)nzP
OPEN=( NODE* )calloc(1,sizeof( NODE ));
6GuTd
CLOSED=( NODE* )calloc(1,sizeof( NODE )); gPn0-)<
//生成起始节点,并放入Open表中 /R|?v{S1
Node=( NODE* )calloc(1,sizeof( NODE )); ",~ZO<P
Node->g = 0; O=K0KOj
//这是计算h值 h7eb/xEto
Node->h = (dx-sx)*(dx-sx) + (dy-sy)*(dy-sy); // should really use sqrt(). +_X*one
//这是计算f值,即估价值 jct=Nee|
Node->f = Node->g+Node->h; fx>QP?Z
Node->NodeNum = TileNum(dx, dy); w!`e!}
Node->x = dx; XnYX@p
Node->y = dy; #bcZ:D@FC
OPEN->NextNode=Node; // make Open List point to first node +L=Xc^
for (;;) a?ete9Q+
{ //从Open表中取得一个估价值最好的节点 ;P'5RCqj
BestNode=ReturnBestNode(); j
0LZ )V
//如果该节点是目标节点就退出 I\Y N!
if (BestNode->NodeNum == TileNumDest) // if we’ve found the end, break and finish F7<u1Rx]
break; K20Hh7cVJ
//否则生成子节点 +mft
GenerateSuccessors(BestNode,sx,sy); 3
[#Rm>,Vu
} `'3&tAy
PATH = BestNode; JPL`/WA0
} $v_&jE
再看看生成子节点函数 GenerateSuccessors: Af@\g-<W_
void AstarPathfinder::GenerateSuccessors(NODE *BestNode, int dx, int dy) o&M.9V?~~
{ <5Ll<0
int x, y; XgXXBKf$
//哦!依次生成八个方向的子节点,简单! \N-3JOVy
// Upper-Left IMM+g]#e
if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y-TILESIZE) ) ZI4dD.B
GenerateSucc(BestNode,x,y,dx,dy); p(="73
// Upper \ntUxPox.
if ( FreeTile(x=BestNode->x, y=BestNode->y-TILESIZE) ) _cC!rq U1
GenerateSucc(BestNode,x,y,dx,dy); yJ]Va $M
// Upper-Right EbX!;z
if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y-TILESIZE) ) QBi]gT@&g
GenerateSucc(BestNode,x,y,dx,dy); ~H
// Right sSwY!";
if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y) ) An`*![
GenerateSucc(BestNode,x,y,dx,dy); |*b-m k
// Lower-Right XjP;O,x
if ( FreeTile(x=BestNode->x+TILESIZE, y=BestNode->y+TILESIZE) ) l\Ww^
GenerateSucc(BestNode,x,y,dx,dy); vGPsjxk&
// Lower Ya!%o> J%t
if ( FreeTile(x=BestNode->x, y=BestNode->y+TILESIZE) ) .,#H]?Wil
GenerateSucc(BestNode,x,y,dx,dy); S-Bx`e9'
// Lower-Left 34N~<-9AY
if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y+TILESIZE) ) -/Wf iE
GenerateSucc(BestNode,x,y,dx,dy); (
C).Vj~
// Left :-Py0{s
if ( FreeTile(x=BestNode->x-TILESIZE, y=BestNode->y) ) k 9z9{
GenerateSucc(BestNode,x,y,dx,dy); vlEW{B;)Z
} @@{5]Y
RB%y($
看看最重要的函数GenerateSucc: +DR$>a
void AstarPathfinder::GenerateSucc(NODE *BestNode,int x, int y, int dx, int dy) NT5'U
{ IOuqC.RJ}o
int g, TileNumS, c = 0; {N/%%O.b
NODE *Old, *Successor; $YcB=l
//计算子节点的 g 值 Q%d1n*;+
g = BestNode->g+1; // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor /"u37f?[^
TileNumS = TileNum(x,y); // identification purposes 09G47YkSy1
//子节点再Open表中吗? N8#j|yf
if ( (Old=CheckOPEN(TileNumS)) != NULL ) // if equal to NULL then not in OPEN list, else it returns the Node in Old SZHgXl3:
{ /9I/^i~
//若在 $#u'XyA
for( c = 0; c <8; c++) if( BestNode->Child[c] == NULL ) // Add Old to the list of BestNode’s Children (or Successors). je2_.^
break; %>i:C-l8
BestNode->Child[c] = Old; tS]
//比较Open表中的估价值和当前的估价值(只要比较g值就可以了) ZCPUNtO
l
if ( g g ) // if our new g value is Parent = BestNode; Kmx^\vDs
Old->g = g; I_u/
Old->f = g + Old->h; x}?<9(nE c
} '"\M`G
} }a6t<m`V
else //在Closed表中吗? `!HD.
E[2c
if ( (Old=CheckCLOSED(TileNumS)) != NULL ) // if equal to NULL then not in OPEN list, else it returns the Node in Old x2#JD|0
{ tZ9i/=S
//若在 TD}<U8I8_
for( c = 0; c<8; c++) if ( BestNode->Child[c] == NULL ) // Add Old to the list of BestNode’s Children (or Successors). uD&B{c+a
break; 5h#h>0F
BestNode->Child[c] = Old; Z,38eQpM
//比较Closed表中的估价值和当前的估价值(只要比较g值就可以了) LEgP-sW
if ( g g ) // if our new g value is Parent = BestNode; XZM3zlg*
Old->g = g; '3(^Zv
Old->f = g + Old->h; e /JQ #A
//再依次更新Old的所有子节点的估价值 J/?Nf2L4
PropagateDown(Old); // Since we changed the g value of Old, we need 6@J=n@J$p
// to propagate this new value downwards, i.e. } p'ZMj&
// do a Depth-First traversal of the tree! )#}>,,S
} $RPW/Lyiq
} FM@iIlY"
else//不在Open表中也不在Close表中 u]J@65~'b
{ 9Yx(u2PQ
//生成新的节点 x%G3L\5
Successor = ( NODE* )calloc(1,sizeof( NODE )); xAQtX=FoX+
Successor->Parent = BestNode; 'YNaLZ20
Successor->g = g; @X2*O9
Successor->h = (x-dx)*(x-dx) + (y-dy)*(y-dy); // should do sqrt(), but since we don’t really V2YK T,5
Successor->f = g+Successor->h; // care about the distance but just which branch looks uepyH
Successor->x = x; // better this should suffice. Anyayz it’s faster. J-F".6i5
Successor->y = y; >ZgzE
Successor->NodeNum = TileNumS; l4Xz r:]
//再插入Open表中,同时排序。 xt{'Be&Ya+
Insert(Successor); // Insert Successor on OPEN list wrt f XpIiJry!6
for( c =0; c <8; c++) if ( BestNode->Child[c] == NULL ) // Add Old to the list of BestNode’s Children (or Successors). _FLEz|%~
break; U@lc1#
BestNode->Child[c] = Successor; T(4d5 fY
} ^NW[)Dq1<
}
--$o$EP`
`&$8/_`
^rkKE
dd
哈哈!A*算法我懂了!当然,我希望你有这样的感觉!不过我还要再说几句。仔细看看这个程 序,你会发现,这个程序和我前面说的伪程序有一些不同,在GenerateSucc函数中,当子节点 在Closed表中时,没有将子节点从Closed表中删除并放入Open表中。而是直接的重新的计算该 节点的所有子节点的估价值(用PropagateDown函数)。这样可以快一些!另当子节点在 Open 表和Closed表中时,重新的计算估价值后,没有重新的对Open表中的节点排序,我有些想不通, 为什么不排呢?:-(,会不会是一个小小的BUG。你知道告诉我好吗?
[原创]游戏地图智能寻路 [A星算法]易源码,有些问题希望探
来源:互联网 发布日期:2011-09-07 11:51:07 浏览:19066次
导读:近期刚刚开始研究外怪,希望,社区的朋友能多多支持下以下代码是本人花了几天时间自行写出来的,可能别人也写过类似代码,但是实现方式肯定不同,目前本代码搜...
相关内容
- 理邦仪器:获盖茨基金会265万美元支持人工智能超声项目
- 北航团队提出全新偏好数据构建框架,助力大模型实现更全面的对齐效果
- 美媒:人工智能企业正涌入中国这个全球最大批发市场
- “AI创业项目仍在寻找市场的认可度”
- 美国科技巨头的AI资本开支,是否正在接近“危险界限”?
- 美国限制之下,中国多家科技公司在硅谷挖掘AI顶尖人才
- 谷歌 Gemini 引入“记忆”功能:AI 记住用户偏好、习惯
- 人工智能大模型怎样投喂数据?人工智能头部企业为何纷纷选择落户四川自贡?
- AI行业存在泡沫吗?
- 研究揭示 AI 对话方面的缺陷:不知道何时该插话
- 从Eliza到AI Agent,人工智能经历了多少“练习时长”?
- 不止OpenAI“猎户座”!谷歌和Anthropic AI模型开发也被爆遇瓶颈
- 首部“超智融合”研究报告:人工智能将助力超级计算机突破发展瓶颈
- 谷歌员工曝AI改进速度放缓,Gemini已成立新团队解决问题
- 四成AI数据中心或陷入“用电荒”,全球能源格局面临重大挑战
- 面对AI浪潮:电信运营商应该All in 还是谨慎为妙?
- 从反垄断监管、AI立法到芯片法案,科技行业关注“特朗普2.0”
- 英伟达秀 Blackwell GPU 肌肉:训练 AI 模型速度比Hopper快2.2倍
- 专访格创东智何军:国内工业大模型应用有机会走在世界前列
- 欧洲科学院郭嵩谈“千模大战”:每个行业会有垂类大模型,AI PC是“杀手级应用”
AiLab云推荐
最新资讯
- AI与半导体行业互为推动,多突破口已显现
- 北航团队提出全新偏好数据构建框架,助力大模型实现更全面的对齐效果
- 专访格创东智何军:国内工业大模型应用有机会走在世界前列
- AI驱动创新,2025年半导体市场或将突破8500亿美元大关!
- 理邦仪器:获盖茨基金会265万美元支持人工智能超声项目
- 面对AI浪潮:电信运营商应该All in 还是谨慎为妙?
- 谷歌 Gemini 引入“记忆”功能:AI 记住用户偏好、习惯
- 欧洲科学院郭嵩谈“千模大战”:每个行业会有垂类大模型,AI PC是“杀手级应用”
- 万卡算力和万亿参数大模型时代,AI存储何时爆发?| ToB产业观察
- 人工智能大模型怎样投喂数据?人工智能头部企业为何纷纷选择落户四川自贡?
本月热点
热门排行
-
马斯克的xAI连发两款新模型,有进步但还谈不上领先
阅读量:90783
-
Meta Llama 3.1-405B AI模型多项跑分超越 OpenAI GPT-4o
阅读量:27078
-
从现在起,GitHub上超1亿开发者可直接访问全球顶级大模型,构建AI应用
阅读量:18311
-
AI创投的那些荒诞故事
阅读量:15996
-
AI时代,超级个体正在崛起
阅读量:14129
-
阿里团队推出 Tora 视频 AI 生成框架:画圈操控物体运行轨迹
阅读量:13574
推荐内容
- 2024山东国际玻璃工业技术展览会
- 2024第二十二届中国广州国际汽车展览会
- 2024年阿尔及利亚国际暖通空调制冷展览会ALGERIA
- 2024第12届中国(青岛)国际茶产业博览会(华巨臣茶博会)
- 2024阿尔及利亚国际建材展
- 2024 第二十三届新加坡国际石油及天然气展览会暨研讨会
- 2024年荷兰阿姆斯特丹船舶游艇设备展览会METS TRADE
- 2024第12届巴基斯坦(卡拉奇)国际防务与军警展
- 2024年俄罗斯莫斯科电力、电网技术展览会
- 2024(京津冀)水果产销对接会
- 2024第二十一届北方(烟台)国际果业博览会(北方果博会 NIFIE)
- 2024第十六届中国(上海)振威国际化工装备博览会(CTEF)
- 2024第七届欧洲(德国不来梅)国际空间技术展
- 2024第十七届上海国际电池工业展览会(振威电池展 CNIBF)
- 2024第二十届上海国际充电设施产业展览会(振威充电设施展 evse)
- 2024第十一届浙江义乌国际智能装备博览会
- 2024第89届全国药品交易会(药交会 PHARMCHINA)
- 2024年中国北京国际高端食品饮料博览会
- 2024年中国(北京)国际有机绿色食品展览会
- IADE2024第三届突尼斯(杰尔巴)国际航空航天与防务展
- 2024年土耳其温室农业展土耳其畜牧机械展GrowTech Eurasia
- 2024中国北京名酒节暨世界葡萄酒博览会
- 2024第十三届杭州国际跨境电商交易博览会(跨交会 ICBE)
- 2024中国健康营养博览会(秋季)(NHNE)
- 2024乌兹别克斯坦食品及包装展 UZ PROD &INTER PACK
- 日本第45届国际建筑建材与家居材料展
- 2024中国国际制造业数智化博览会
- 2024第29届深圳国际服装供应链博览会(秋季)(FS展 Fashion Source)暨AW深圳原创设计时装周
- 2024越南(胡志明)轴承展览会
- 2024越南(胡志明)橡胶机械及塑料展览会
- 2024越南(胡志明)五金机械展览会
- 2024秋季中国(广州)国际茶业博览会
- 2024越南(胡志明)电机及线圈展览会
- 2024越南(胡志明)电线电缆展览会
- 2024越南(胡志明)润滑油及应用技术展览会
- 2024越南(胡志明)焊接与切割展览会
- 2024越南(胡志明)电池产品展览会
- 2024中国国际天然提取物和健康食品配料展览会(FIC-健康展2024)暨第23届全国秋季食品添加剂和配料展览会
- 2024厦门国际眼镜业展览会(厦门眼镜展)
- 2024第十八届中国宁波中小工厂展览会
- 2024越南(胡志明市)国际工业技术装备及产品展览会
- 2024深圳国际照明展览会
- 2024越南(胡志明)煤矿技术设备展览会
- 2024第20届越南胡志明国际工业展览会
- 2024第二十二届中国(北京)国际医疗旅游展览会(正和医疗旅游展 CMTF)
- 2024越南(胡志明)金属及冶金展览会
- 2024年越南国际制药装备及医疗器械展览会
- 2024越南国际表面处理及涂料涂装展览会
- 2024越南(胡志明)国际复合材料展览会
- 2024越南(胡志明)工程机械设备展览会
- 2024越南(胡志明)锅炉及压力容器展览会
- 2024越南(胡志明)化工展览会
- 2024越南(胡志明)工业自动化及仪器仪表展览会
- 2024越南(胡志明)机床工具展览会
- 2024越南(胡志明)金属加工及焊接技术展览会
- 2024越南(胡志明)铝工业展览会