地址发布 老王说明书 宣传中心
此板块只作为纯讨论

正经话题,不搞色情!贤者时间必备
查看: 7518|回复: 29
收起左侧

[学习讨论] RPG游戏的寻路算法——从绯月讲起

[复制链接]
 楼主| 发表于 2023-12-25 18:31:47 | 显示全部楼层 |阅读模式
本帖最后由 navebayes 于 2023-12-26 12:02 编辑 - F0 c0 I2 |; F/ u' S. X2 @+ U(欢迎访问老王论坛:laowang.vip)

2 n% \0 N+ y8 c. h0 ^最近正在玩个游戏,也算是国产之光绯月仙行录,这个游戏哪里都好就是bug太多,并且作者过于摆烂,以至于有很多玩家都认为这个游戏就是故意拖着吃赞助的(bushi)
# P9 f2 q7 V( @, k9 `言归正传,在游玩这个游戏的过程中,我在一个评论区里看到这样一段话:自从玩了绯月之后,对于其他RPG游戏都看不上眼了,因为这个游戏独创了自动寻路的功能,可以说是RPG类游戏的里程碑式壮举。; o) f/ P; Y" O: o! G* R(欢迎访问老王论坛:laowang.vip)
我对此感到好奇,因为从前从来没有游玩RPG类游戏的经验,但我学过一点点算法,于是我打算用一些浅显易懂的方式说说自动寻路这样一个功能的实现。8 D1 c/ j! v) m, n  m% B" X. L4 y(欢迎访问老王论坛:laowang.vip)
' H0 X' h  W+ [(欢迎访问老王论坛:laowang.vip)
主流的寻路算法:深度优先,广度优先,Dijkstra,A* 等,我这里主要讲讲后两种。* k: R0 a7 f" I, A& u( Z" ](欢迎访问老王论坛:laowang.vip)
2 I$ N8 `: s9 x8 C7 R(欢迎访问老王论坛:laowang.vip)
Dijkstra算法:这个算法是目前很多地图软件都在使用的算法,采用OPEN,CLOSE表的方式实现寻路功能。
/ ~' P6 P! [2 ^7 c; T1 M    创建两个表,OPEN, CLOSE。
: O7 b* P. }7 g& f) S9 p. XOPEN表保存所有已生成而未考察的节点,CLOSED表中记录已访问过的节点。* K" Y9 u4 R' w$ k. g( S3 u(欢迎访问老王论坛:laowang.vip)
1. 访问路网中里起始点最近且没有被检查过的点,把这个点放入OPEN组中等待检查。! R1 t: u5 ^6 Y(欢迎访问老王论坛:laowang.vip)
2. 从OPEN表中找出距起始点最近的点,找出这个点的所有子节点,把这个点放到CLOSE表中。0 r9 `3 M& S, B5 q(欢迎访问老王论坛:laowang.vip)
3. 遍历考察这个点的子节点。求出这些子节点距起始点的距离值,放子节点到OPEN表中。2 }1 \7 F- J& m# Q- u(欢迎访问老王论坛:laowang.vip)
4. 重复2,3,步。直到OPEN表为空,或找到目标点。
- V$ K) ]/ W1 D, P; g4 b  C' `# H" H$ @! e(欢迎访问老王论坛:laowang.vip)
实际写代码还是比较占行数的,直接给出链接如下。+ H5 ^* [/ O6 [/ ]. H) B6 n; G. A  ](欢迎访问老王论坛:laowang.vip)
参考:https://blog.csdn.net/YiYeZhiNian/article/details/122217450( s3 Y- A7 F5 f" E(欢迎访问老王论坛:laowang.vip)

! o- z- F1 s( R; ?用这个算法,我写过一个课程作业,具体就是对于各个城市的地铁最短路径规划,大致还是比较成功的。先说说个人对于Dijkstra算法设计地铁线路规划:
  g4 O: s8 L; p1.首先用爬虫爬到该城市的地铁网络,包含站点名称,该站点经纬度和线路图,并生成excel表格。用该excel表格生成pickle文件,方便直接调用。- \9 Z9 W8 D: S; I1 a, b$ M(欢迎访问老王论坛:laowang.vip)
2.注册高德地图开发者账号(该功能需要实名),得到一个key用于调用api(每日上限100次,超过付费,我调试到后面不让我调试了...)! }0 q6 v6 I1 S' _/ E& R% I" O(欢迎访问老王论坛:laowang.vip)
3.输入始发地和目的地,并通过api返回两个位置的经纬度坐标。
: P3 O+ t$ @5 d$ f$ D* I( G5 a- p4.比较两地理位置之间的最近地铁站,并根据Dijkstra算法实现路径规划。& [( B2 R% s" [; G" a- D) _(欢迎访问老王论坛:laowang.vip)
5.Dijkstra算法的本质就是不断选择新顶点并更新已处理表,并将他和邻居节点进行比对,当所有节点都被处理后即为最短路径* N( @5 g0 q" Y/ A3 Q7 R(欢迎访问老王论坛:laowang.vip)
至此,已初步完成具体工作流程。9 |4 i: g; m* j(欢迎访问老王论坛:laowang.vip)
  1. def get_nearest_subway(data,longitude1,latitude1):- b0 T0 z0 _0 H" ^" c(欢迎访问老王论坛:laowang.vip)
  2.   #找最近的地铁站
    / t' L& D3 `( D
  3.   longitude1=float(longitude1)
    7 d  n9 |3 @% S. w+ b, u' Y$ R4 X- f
  4.   latitude1=float(latitude1)
    & t, R0 p' e) J3 Y
  5.   distance=float('inf')  X# @4 E) I3 x) y2 X: Y& r(欢迎访问老王论坛:laowang.vip)
  6.   nearest_subway=None5 H; {, J7 X$ F. @( \) X( A" |$ |(欢迎访问老王论坛:laowang.vip)
  7.   for i in range(data.shape[0]):/ [' I, N1 E# O3 F(欢迎访问老王论坛:laowang.vip)
  8.     site1=data.iloc[i]['name']   
    ' q0 X2 Z% e: ?2 _- q
  9.     longitude=float(data.iloc[i]['longitude']), @; B# X/ r& p, E(欢迎访问老王论坛:laowang.vip)
  10.     latitude=float(data.iloc[i]['latitude'])    #分别将经纬度代入,计算与目标之间的欧氏距离
    1 K# s3 g$ F6 e/ M
  11.     temp=geodesic((latitude1,longitude1), (latitude,longitude)).m   #temp对其遍历即可,这里对比各个地铁站的欧氏距离
    ; B( e. Y* k0 n6 J6 k! s8 ]3 C% [
  12.     if temp<distance:
      f& Q0 @* x( s  g
  13.      distance=temp$ A" E5 x' x/ I' X(欢迎访问老王论坛:laowang.vip)
  14.      nearest_subway=site1/ l- t0 |; `7 ~! b7 ^& H: r# E(欢迎访问老王论坛:laowang.vip)
  15.      return nearest_subway  
复制代码
  1. def subway_line(start,end):    #创建点之间的距离
    ( @! ^+ b% {' F  L/ ^
  2.   file=open('graph.pkl','rb')
    0 C3 P+ E5 d$ ?
  3.   graph=pickle.load(file)   #现在我们有了各个地铁站之间的距离存储在graph
    % V$ N& K9 L  T" X' w
  4.   costs={}    #创建节点的开销表,cost是指从start到该节点的距离
    ! w2 o8 X( Z  m  v1 x& O
  5.   parents={}
    1 k: U. v6 ], l4 s2 y
  6.   parents[end]=None# \+ i: W/ u" D' I1 X; I6 a; A(欢迎访问老王论坛:laowang.vip)
  7.   for node in graph[start].keys():* b+ X# I) `' @, F(欢迎访问老王论坛:laowang.vip)
  8.     costs[node]=float(graph[start][node])
    ; W5 w; `  D" S
  9.     parents[node]=start
    + p# x4 g% ^9 N& E" e+ p& b
  10.     costs[end]=float('inf')    #终点到起始点距离为无穷大6 p# x: _9 b! C. H6 i& m3 K  o' \(欢迎访问老王论坛:laowang.vip)
  11.     processed=[]      #记录处理过的节点list/ L3 {3 @" O" w! Y(欢迎访问老王论坛:laowang.vip)
  12.     shortest_path=dijkstra(start,end,graph,costs,processed,parents)4 Z8 r8 a+ C" @6 }+ o0 t4 X$ r(欢迎访问老王论坛:laowang.vip)
  13.     return shortest_path
复制代码
  1. #计算图中从start到end的最短路径
    - V. c8 O  ?3 w/ s" n& S8 ~. O5 o* R. p
  2. def dijkstra(start,end,graph,costs,processed,parents):: ^& k: _) \1 n4 ^( P(欢迎访问老王论坛:laowang.vip)
  3.     #查询到目前开销最小的节点
    ' t# N, C4 u& L
  4.     node=find_lowest_cost_node(costs,processed)
    : S, [4 R1 E+ A% _
  5.     #使用找到的开销最小节点,计算它的邻居是否可以通过它进行更新4 a# Y, B5 k/ ^. K  s* Y4 u(欢迎访问老王论坛:laowang.vip)
  6.     #如果所有的节点都在processed里面 就结束0 u+ C# Y. R8 G(欢迎访问老王论坛:laowang.vip)
  7.     while node is not None:1 X! J- i  k8 v9 I8 s2 b(欢迎访问老王论坛:laowang.vip)
  8.     #获取节点的cost
    * N2 o) ^* F2 J5 B" M2 }3 Z
  9.       cost=costs[node]  #cost 是从node 到start的距离
    ' I5 y' ?" L# n" |- z
  10.       #获取节点的邻居
    : w0 d. x7 _& H; i& B0 a4 ?9 h
  11.       neighbors=graph[node]
    7 A. L1 f5 J8 ?5 r9 `. `' @
  12.       #遍历所有的邻居,看是否可以通过它进行更新
    & L3 d3 {7 t$ o& T6 `* x/ {! `
  13.       for neighbor in neighbors.keys():
    # r+ c  X. v; g# O5 @
  14.       #计算邻居到当前节点+当前节点的开销
    ; J1 ]- P3 D# K2 }) E7 E
  15.         new_cost=cost+float(neighbors[neighbor])! E  K  R  G- T% C(欢迎访问老王论坛:laowang.vip)
  16.         if neighbor not in costs or new_cost<costs[neighbor]:
    : v. O4 g* L  e- J
  17.         costs[neighbor]=new_cost
    : ^3 I6 J7 C0 c: b* J
  18.         #经过node到邻居的节点,cost最少% j& l2 |5 y, a1 W- z) u(欢迎访问老王论坛:laowang.vip)
  19.         parents[neighbor]=node
    1 p- u  a2 \! o  c
  20.         #将当前节点标记为已处理
    . r: M8 b" I2 @6 E9 l$ j9 D. g
  21.   processed.append(node)3 V4 }# `2 |- }5 t(欢迎访问老王论坛:laowang.vip)
  22.   #下一步继续找U中最短距离的节点  costs=U,processed=S' R9 \+ r% u2 N' P8 g2 ?% w/ ?; P% ?(欢迎访问老王论坛:laowang.vip)
  23.   node=find_lowest_cost_node(costs,processed)
复制代码
  1. def find_lowest_cost_node(costs,processed):
    4 n, d% z& Y" [% L. k
  2.     #初始化数据% j- `/ J/ w7 G2 N(欢迎访问老王论坛:laowang.vip)
  3.   lowest_cost=float('inf') #初始化最小值为无穷大
    7 ~# C3 c0 y1 q+ g
  4.   lowest_cost_node=None" m2 ^2 H% Z% J, N& ]- I(欢迎访问老王论坛:laowang.vip)
  5.     #遍历所有节点+ W3 M& z+ z1 w, N3 l, ^( t(欢迎访问老王论坛:laowang.vip)
  6.   for node in costs:  H5 e8 p. Z1 q5 c* Q1 r- X(欢迎访问老王论坛:laowang.vip)
  7.     #如果该节点没有被处理
    ( X* Y$ j% C* f
  8.     if not node in processed:
    . x1 f% o0 m+ v0 y; _7 N( K( k5 r
  9.       #如果当前的节点的开销比已经存在的开销小,那么更新该节点为最小开销的节点: [' D$ j" b" E; L(欢迎访问老王论坛:laowang.vip)
  10.       if costs[node]<lowest_cost:
    ! Z, L; q+ }0 j9 @, J
  11.       lowest_cost=costs[node]: J' u/ D$ o- ]5 T; ]4 v(欢迎访问老王论坛:laowang.vip)
  12.       lowest_cost_node=node
    & ~! i3 i6 G; C0 Y. Y5 H
  13.     return lowest_cost_node
复制代码
上面这段基本上搬运的,主要是他代码已经写的很好了,注释也写的不错,但我写的时候爬虫调不出来(反爬虫技术可以的),最后是我手动去地图里找经纬度得到的结果。3 O/ _* T; t. Q9 m6 w: [: o(欢迎访问老王论坛:laowang.vip)
引用:https://blog.csdn.net/fengdu78/article/details/111570695
) i3 ]- h4 m% \9 f! n

' c$ o* o6 F0 ?4 n7 J4 J" g! A) n% r(欢迎访问老王论坛:laowang.vip)

- h, W9 b5 s/ O; GA*算法:这个算法也是非常著名的算法,与Dijkstra算法相比,增加了启发式函数 ---- 启发函数的好坏直接决定了算法的效率和结果。由此衍生的D*(动态A算法)算法也被广泛运用于各类游戏中。D*的搜索效率高的原因就在于,当计划路径上某点被阻碍,因为是反向指针,可以定位到被堵节点的上一节点。也就是说只需重新搜索很小的一部分,其余部分仍然使用初始规划出的路径,大大提高了重规划的效率。# O& t. d$ J$ s" k. l(欢迎访问老王论坛:laowang.vip)

: B% t. c! ]9 u- z" T- }; H) d# Z& V& i" u9 g+ W" T, [5 Z(欢迎访问老王论坛:laowang.vip)
额外补充-dfs&bfs逻辑
6 P! v5 M  L: o7 c+ a2 ?; c深度搜索(dfs)和广度搜索(bfs)的算法逻辑可以说是最具有代表性的,基本任何有关于寻路的算法都没法绕开他俩。我担心可能没了解这2个算法直接去看Djkta和A*会有些懵逼
  n" l- A/ h8 G6 W( G" {9 x" n' h3 w# J5 y5 T$ u(欢迎访问老王论坛:laowang.vip)
深度搜索(dfs)
! O# H8 T! M) l+ w4 ^  [$ }

- p1 K) B# W6 _# ?  L4 n( Mdfs就和它字面意思一样,是往更深的地方找(deepfound)
3 m) [8 y+ |- N- n它的核心思想很简单:( ~2 J  Y" _8 k2 d% [+ m& g; h(欢迎访问老王论坛:laowang.vip)
一直往前走,走不通就回头, B* d6 o1 I, B( f3 ~! P(欢迎访问老王论坛:laowang.vip)
7 U% k; R2 F# F) r# J$ k# W$ T. Q(欢迎访问老王论坛:laowang.vip)
顺序?当然是长幼啦,有长立长无长立幼 (1会先找2而非6,在2时会先找4而非5 ,直到4发现3 发现无路可走再back回去)
. P" L$ Q  n2 l! j, {# H大致伪代码如下. y- G( D! S- y5 @1 T( D(欢迎访问老王论坛:laowang.vip)
  1. input 地图
    4 d0 K" Z  B% u1 u" `* W
  2. create 已经过点
    , W  h9 m: A# e6 {# d) @' N
  3. create 结果存储
    ( `3 \0 m; G6 X" ^  G+ `1 q. K
  4. * c$ R" k( u  \( I- @(欢迎访问老王论坛:laowang.vip)
  5. type node{
    # x( C8 X* N7 A  O
  6. node nextNode[];//下一节点们  ^) _" F8 R4 y7 X. b- f' e(欢迎访问老王论坛:laowang.vip)
  7. nodeval;//节点标记物
    7 p7 ?- p1 b. n: S
  8. }1 Y, ^( _1 L  Z4 c; z( O7 U(欢迎访问老王论坛:laowang.vip)

  9. ( l1 R; M  H2 Z% R; `6 l- b4 I
  10. 7 e. t- J* f7 @" p& G% L- l, l7 R# Q0 o(欢迎访问老王论坛:laowang.vip)
  11. //这里开始是函数
    " v9 m" U; ^2 f5 L7 w; ], |
  12. fun dfs(node* nowPoint)
    ) S( y& [- @% Q7 s4 B# B, P# Q1 D
  13. {, q! s) _  G: R! W. p4 {8 e(欢迎访问老王论坛:laowang.vip)
  14. define u 为 nextNode[] size
    ) F+ v0 a1 ]# o! e
  15. int  key;% E: ?: ^6 N- i9 a; J4 G(欢迎访问老王论坛:laowang.vip)
  16. + c) x+ T% k9 A, L% |(欢迎访问老王论坛:laowang.vip)
  17. for i in u {
    - C# f( i9 F" Q  K, d$ g7 [0 H: g9 {
  18.       if (nowPoint.noteval == target)
    * p! a! i' K6 @5 I* n: M9 r
  19.         {1 t, H9 E- O. T8 z* B. h(欢迎访问老王论坛:laowang.vip)
  20.             结果存储[0] = nowPoint.noteval;
    0 V) {% x& v4 n; x0 P9 ~
  21.             return 0 ;4 T, h; }2 a) x! e(欢迎访问老王论坛:laowang.vip)
  22.         }  3 D0 H3 W5 Y" j' z(欢迎访问老王论坛:laowang.vip)
  23.       else if( key = (dfs(nowPoint->nextNode[i])) != -1 ) //如果dfs这次没有返回负1(即 找到终点了)
    ; b/ v, y2 @" l. i- Z$ u0 r% j3 ?
  24.             {
    6 k+ y% G% F6 e' F5 d  u$ q
  25.                 结果存储[key] = nowPoint.noteval;
    * Y0 P6 ]1 d( a' r$ O. t  K
  26.                 return key+1;         
    / N4 U" U& a) w+ h' r4 N' I
  27.             }   / f* `) s/ s5 M( y/ B) |/ X, @(欢迎访问老王论坛:laowang.vip)
  28.         else- V: W2 W/ Y! F6 @9 q. `(欢迎访问老王论坛:laowang.vip)
  29.             {
    # `# p. S) A* ^2 N
  30.                 /********************/9 f& H, v* B% I8 l0 j5 x(欢迎访问老王论坛:laowang.vip)
  31.                 /**        nothing          **/+ w, O6 F& x2 Y(欢迎访问老王论坛:laowang.vip)
  32.                 /********************/
    % o9 ]4 y/ Q* ], _+ s. B3 Y
  33.             }    8 Z1 F+ `) C' x(欢迎访问老王论坛:laowang.vip)

  34. - B# m- F  \  F- z8 b! M2 Q
  35.         2 o! g+ \9 x# n(欢迎访问老王论坛:laowang.vip)
  36.    }   ; g3 {; r( P0 s! y" N# W(欢迎访问老王论坛:laowang.vip)
  37.     return -1;) h8 K) I3 Y- ~5 N# r0 C(欢迎访问老王论坛:laowang.vip)
  38. }! G, C9 }* \% W  b) c, S(欢迎访问老王论坛:laowang.vip)
复制代码
就那么短,你只需要确定是不是就行了
$ b4 d9 ?! n- ^) h( A3 f! T# }& j是不是很简单:p 但是这就是一个比较原始的寻路算法的模样-顺其自然流
; P7 B0 k0 V( ~4 L) n
* q. ~. _7 R1 f( t8 u在dfs算法中,你需要做的就是 询问+上抛5 r: X# b' m. O" }- D(欢迎访问老王论坛:laowang.vip)
当然,dfs算法唯一能保证的就是‘找得到路’,这也是为什么纯粹的dfs算法不常用于生产环境中( |+ W' B& b9 T* w' |' d$ \(欢迎访问老王论坛:laowang.vip)
7 r* i4 S$ u2 ], _" N(欢迎访问老王论坛:laowang.vip)

/ T. Y! j- s- [3 z( o" K广度搜索(bfs)
% T. E; }8 w+ q5 D* F; p知道深度,广度就很容易联想了 先找周围嘛 无论如何,先找周围
+ a/ b6 O, M: L) N6 D7 x! f! t: q! l" ]( w5 W$ E7 A(欢迎访问老王论坛:laowang.vip)
这里不进行代码补充了,只简单地说一下逻辑
3 C8 `5 y- h( Z
6 Q  V( q8 [: c8 n: G" w$ f这个算法分以下几步:
- [1 E1 \9 ?2 }' [& D  i9 q0,准备一个队列(就是那个queue),然后丢入我们的起点 命运的齿轮开始拨动
/ n; O2 h- Z% l; {* A) J, d$ l9 ]6 n9 {" ?; }(欢迎访问老王论坛:laowang.vip)
1,询问当前节点是否终点?- L6 J- n6 Q5 S$ N( @6 o+ l; F(欢迎访问老王论坛:laowang.vip)
2,将自己的nextNode 塞入队列中(除了访问过的)
  j% o1 K3 t  d3 I  C4 A* D9 }3,从队列里output一个节点,作为下一个‘当前节点’- }2 ]0 g' `; x, m; W0 P+ ^(欢迎访问老王论坛:laowang.vip)
8 R% Z8 X' V# y* s4 Q" M(欢迎访问老王论坛:laowang.vip)
然后就是循环1~37 j* \3 W0 n& q, C+ b3 I, s: w(欢迎访问老王论坛:laowang.vip)
3 H5 K9 _& a. s' R, Y& D(欢迎访问老王论坛:laowang.vip)
是不是很简单?3 ^" b& ~; U- |) i  C(欢迎访问老王论坛:laowang.vip)
9 B1 h/ C/ I8 ~, j( y+ Y8 X; q/ j(欢迎访问老王论坛:laowang.vip)
这2个算法都属于随性流,一个适合终点远一个适合终点近。但无论如何这俩都暂时没有比较最优的功能
2 V( K$ a' Z1 R" v4 y4 A2 J因为他们刚~满~十~八~岁~的审敛条件就只是找得到路
' ]% \" N0 A. d0 t& B8 q% B) v! ?2 W; L(欢迎访问老王论坛:laowang.vip)
但你可以发现哦?如果将dfs的‘长幼判断’换成‘最优判断’,将呆值传递换为矩阵存储 就是dj算法了诶(a*也是类似的)) T$ f6 U* \7 b+ \+ _- b(欢迎访问老王论坛:laowang.vip)
而bfs作为‘扩散式搜索’显然地在进行多点寻路时效用更加明显2 D1 w: M- \. V3 U+ D(欢迎访问老王论坛:laowang.vip)
如果觉得寻路算法很难的话,不妨先从dfs&bfs开始了解
5 c. k! Z5 U) A. g* g
$ C' ^  Q8 s2 R2 r. `
: V  |/ m, {/ |9 P
# M% W0 j& Y2 Z2 @& p; g' Z( L6 q& i(欢迎访问老王论坛:laowang.vip)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?免费注册

x

评分

参与人数 1软妹币 +235 收起 理由
navebayes + 235 cheese!!

查看全部评分

本帖被以下淘专辑推荐:

回复

使用道具 举报

发表于 2023-12-25 20:31:04 手机版 | 显示全部楼层
Applcu 发表于 2023-12-25 20:19# s3 G$ ~( d& S(欢迎访问老王论坛:laowang.vip)
我在想怎么算说明运作逻辑.....真贴上去么?这个编辑器到底怎么用啊" X- V3 V" q4 K(欢迎访问老王论坛:laowang.vip)
...
) H9 V+ l& m6 F' ~. _8 ?" W9 u(欢迎访问老王论坛:laowang.vip)
有一个代码框功能,可以用那个。主要编辑的话建议用正八经的md编辑器(我用的是国产的typora)
回复 支持 3 反对 0

使用道具 举报

发表于 2023-12-25 20:25:06 | 显示全部楼层
navebayes 发表于 2023-12-25 20:11% T1 O5 D# U4 i* t6 Z(欢迎访问老王论坛:laowang.vip)
申请失败,原因:对算法本身描述过少,请更具体地说明算法的运作逻辑和方式,如果可以最好给出部分低代码
) P& W8 f# w1 v) a/ e4 ^. C$ S
2 i2 R! v7 {- o+ G ...

* H* B* {% _' z3 N/ D, D8 i1 c& K2 i啊这。不如解释一下单源最短路径问题中对于负权值和负权值回路为什么不能使用上述算法+ X7 x, e) X+ l& q(欢迎访问老王论坛:laowang.vip)
! a- ^% [9 J; M9 k# g6 V0 k; y" k(欢迎访问老王论坛:laowang.vip)
这玩意考试考得头昏脑涨,我tm 深度生成树画错了,越想越气 怎么会这么蠢
" S- a0 b/ e$ Y: S2 z
回复 支持 2 反对 0

使用道具 举报

 楼主| 发表于 2023-12-25 23:28:47 | 显示全部楼层
昔有佳人公孙氏 发表于 2023-12-25 23:082 z, u: X. E, A  E8 e* ?, A3 i( X# r(欢迎访问老王论坛:laowang.vip)
其实目前,本科生能接触到的寻路算法 无外乎迪杰斯特拉和弗洛伊德 一个不吃负值 一个不吃负环
4 s! S4 X7 Q/ s1 _但其实寻找最 ...
4 z1 a* u! y2 m9 R, R(欢迎访问老王论坛:laowang.vip)
黏菌那个早有耳闻,确实是大自然的力量。我之后还想写点加密算法,比如AES,RSA,ECC之类的,其实这个地铁的算法也是我的一个课设,我大概花了两天就搞完了,我的主专业课是自控/单片机/数电/模电/嵌入式之类的,更偏自动化这个方向,算法我研究的不深。这个当毕业论文可能还是有一些勉强的,个人感觉工科是要做出一点实物的东西,当然不同学校可能要求不尽相同。
: @" l9 ^/ s3 n" D, |, J
9 A% e1 r& r! [) E8 K9 s
) W$ K: p: w: C
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-12-25 21:58:28 | 显示全部楼层
先说说个人对于Dijkstra算法设计地铁线路规划:
' M! R0 z6 J& p. G3 o* ~% w) y1.首先用爬虫爬到该城市的地铁网络,包含站点名称,该站点经纬度和线路图,并生成excel表格。用该excel表格生成pickle文件,方便直接调用。0 `, h, {' Y0 z: j: ]) ~4 x% r; k(欢迎访问老王论坛:laowang.vip)
2.注册高德地图开发者账号(该功能需要实名),得到一个key用于调用api(每日上限100次,超过付费,我调试到后面不让我调试了...)! Z  g3 ^+ p" {( Z" y(欢迎访问老王论坛:laowang.vip)
3.输入始发地和目的地,并通过api返回两个位置的经纬度坐标。
- @2 d4 x3 r( J: ]: l4.比较两地理位置之间的最近地铁站,并根据Dijkstra算法实现路径规划。9 N9 r% _/ p) k0 `! z8 S(欢迎访问老王论坛:laowang.vip)
5.Dijkstra算法的本质就是不断选择新顶点并更新已处理表,并将他和邻居节点进行比对,当所有节点都被处理后即为最短路径
- P( M3 O8 r/ W: Q; Z/ Y* V% j至此,已初步完成具体工作流程。. d9 R! y* D8 i+ i- d(欢迎访问老王论坛:laowang.vip)
  1. def get_nearest_subway(data,longitude1,latitude1):
    ) G4 G) _# b: `% `
  2.     #找最近的地铁站. t9 d, c1 z0 j$ B* P- `(欢迎访问老王论坛:laowang.vip)
  3.     longitude1=float(longitude1)
    ) i) g( O2 l; f2 i' E
  4.     latitude1=float(latitude1)
    " [0 s/ y+ S. w- d+ J, m
  5.     distance=float('inf')
    + Z; X& y: b3 _9 A% o
  6.     nearest_subway=None% `: [" y) V- o(欢迎访问老王论坛:laowang.vip)
  7.     for i in range(data.shape[0]):8 s' P2 @8 h  ~- h9 h3 T" Q/ s(欢迎访问老王论坛:laowang.vip)
  8.   site1=data.iloc[i]['name']   
    6 Q; ^# f, _, ^( M; C  Q6 X3 ?
  9.   longitude=float(data.iloc[i]['longitude'])
    7 ~5 o% B  v2 o" |
  10.   latitude=float(data.iloc[i]['latitude'])    #分别将经纬度代入,计算与目标之间的欧氏距离# p+ f6 s5 U. ?; y+ I(欢迎访问老王论坛:laowang.vip)
  11.   temp=geodesic((latitude1,longitude1), (latitude,longitude)).m   #temp对其遍历即可,这里对比各个地铁站的欧氏距离
    9 Y, o+ o# N: n2 w" s; o
  12.   if temp<distance:1 G' c& C$ D3 S& c6 u! c(欢迎访问老王论坛:laowang.vip)
  13.     distance=temp4 i8 [% v( |( V5 D/ M, C(欢迎访问老王论坛:laowang.vip)
  14.     nearest_subway=site1) ~& K2 G- A5 S4 x8 b# @2 M(欢迎访问老王论坛:laowang.vip)
  15.     return nearest_subway  
复制代码
  1. def subway_line(start,end):    #创建点之间的距离2 K% g+ k8 [6 Q" p" i/ t- ?(欢迎访问老王论坛:laowang.vip)
  2.     file=open('graph.pkl','rb')
    # i2 Y( `) W- _8 u0 ~% V! N2 T
  3.     graph=pickle.load(file)   #现在我们有了各个地铁站之间的距离存储在graph( l, Y" r2 D/ ~(欢迎访问老王论坛:laowang.vip)
  4.     costs={}    #创建节点的开销表,cost是指从start到该节点的距离
    * i7 b/ ]: v9 i+ ~9 I
  5.     parents={}
    8 z; f5 h. s/ e# D
  6.     parents[end]=None9 @8 A3 P% L7 m1 D8 C(欢迎访问老王论坛:laowang.vip)
  7.     for node in graph[start].keys():5 t9 d- l( P; ^) h+ f& I, E3 c(欢迎访问老王论坛:laowang.vip)
  8.   costs[node]=float(graph[start][node])
    : u% s5 b2 x) J
  9.   parents[node]=start
    1 \9 q1 n. o9 U* J( U. x1 a
  10.     costs[end]=float('inf')    #终点到起始点距离为无穷大
    3 j. y* a. Q2 r
  11.     processed=[]      #记录处理过的节点list
    ! x6 n  W$ i+ m
  12.     shortest_path=dijkstra(start,end,graph,costs,processed,parents)9 i% R! @4 A3 K# q6 O  |(欢迎访问老王论坛:laowang.vip)
  13.     return shortest_path
复制代码
  1. #计算图中从start到end的最短路径
    $ Q3 ]) |) u( p9 ?! W, W
  2. def dijkstra(start,end,graph,costs,processed,parents):
    0 A% L5 G% e# [3 p' N
  3.     #查询到目前开销最小的节点1 V1 `4 _; t4 m  e6 {3 ~! A5 K4 }(欢迎访问老王论坛:laowang.vip)
  4.     node=find_lowest_cost_node(costs,processed)
    ) w" p! `, G; j5 l: S' H4 p
  5.     #使用找到的开销最小节点,计算它的邻居是否可以通过它进行更新
    4 p: G. ]: G$ D* M
  6.     #如果所有的节点都在processed里面 就结束
    8 j; j+ Y/ `$ Z1 b6 f
  7.     while node is not None:
    / C' p& l: i! k5 b. d
  8.   #获取节点的cost
    # c8 p# {% n' K9 W7 u& K
  9.   cost=costs[node]  #cost 是从node 到start的距离$ e' ?+ X" ?. f% n( I2 H(欢迎访问老王论坛:laowang.vip)
  10.   #获取节点的邻居4 T& ~! a1 ^$ t* K9 U7 a(欢迎访问老王论坛:laowang.vip)
  11.   neighbors=graph[node]
    , v5 Q! S; b! N
  12.   #遍历所有的邻居,看是否可以通过它进行更新
    : @/ u* i4 t; I. a
  13.   for neighbor in neighbors.keys():
    $ N* ]9 X9 P  u6 {2 X6 h4 z
  14.     #计算邻居到当前节点+当前节点的开销9 H6 R0 b# u  _+ ~$ Q(欢迎访问老王论坛:laowang.vip)
  15.     new_cost=cost+float(neighbors[neighbor])
      u" Q& A+ y; X# a# g
  16.     if neighbor not in costs or new_cost<costs[neighbor]:
    8 k: l. R$ ]2 i
  17.       costs[neighbor]=new_cost
    , E; _0 Z  q" i1 o" `
  18.       #经过node到邻居的节点,cost最少/ T9 w8 w8 J5 g5 d) T(欢迎访问老王论坛:laowang.vip)
  19.       parents[neighbor]=node+ ^6 M& ?" K* G4 q3 O(欢迎访问老王论坛:laowang.vip)
  20.   #将当前节点标记为已处理$ J9 V) D  D- ]1 w) i- [(欢迎访问老王论坛:laowang.vip)
  21.   processed.append(node)7 M; v' R4 B* X* I4 h# Z# E(欢迎访问老王论坛:laowang.vip)
  22.   #下一步继续找U中最短距离的节点  costs=U,processed=S
    " Z  \! U& a1 q# o5 p! U& g
  23.   node=find_lowest_cost_node(costs,processed)
复制代码
8 n& j) `7 _. H- s3 X(欢迎访问老王论坛:laowang.vip)
* q# D1 i: y  l" L, Z2 u9 @5 `6 Y: s(欢迎访问老王论坛:laowang.vip)
  1. def find_lowest_cost_node(costs,processed):
    ! P' N% ?4 l; {  Z
  2.     #初始化数据2 K% A& V: |, q$ `- u(欢迎访问老王论坛:laowang.vip)
  3.     lowest_cost=float('inf') #初始化最小值为无穷大
    ; l; _* Y: X# y+ }
  4.     lowest_cost_node=None- t- J9 z& Q* V; b% Y8 K0 f% D5 Q' \(欢迎访问老王论坛:laowang.vip)
  5.     #遍历所有节点
    - X2 h" E' \5 B3 z
  6.     for node in costs:
    ( L) l; e- Q& X- A! c7 ~
  7.   #如果该节点没有被处理
      s: L3 u4 q3 p+ |3 j" B
  8.   if not node in processed:
    1 e, d) N7 j7 o$ t8 ~6 u
  9.     #如果当前的节点的开销比已经存在的开销小,那么更新该节点为最小开销的节点
    4 N/ a6 X) Z1 w9 W( h1 V) x
  10.     if costs[node]<lowest_cost:
      h" v/ \* N4 C; V2 A
  11.       lowest_cost=costs[node]
    " b" _  a2 b" D1 ~7 W/ D
  12.       lowest_cost_node=node" Q( w* j% f- @1 S(欢迎访问老王论坛:laowang.vip)
  13.     return lowest_cost_node
复制代码
上面这段基本上搬运的,主要是他代码已经写的很好了,注释也写的不错,但我写的时候爬虫调不出来(反爬虫技术可以的),最后是我手动去地图里找经纬度得到的结果。* U8 t2 y# r+ Z- u+ x5 [! W9 V(欢迎访问老王论坛:laowang.vip)
引用:https://blog.csdn.net/fengdu78/article/details/111570695' K. B) K& G4 O! m(欢迎访问老王论坛:laowang.vip)
回复 支持 1 反对 0

使用道具 举报

发表于 2023-12-25 20:11:24 手机版 | 显示全部楼层

修改修改

本帖最后由 navebayes 于 2023-12-25 20:14 编辑 + r9 Y$ Y0 x$ `% |, n(欢迎访问老王论坛:laowang.vip)

; ~% K" U6 w1 u9 B5 t申请失败,原因:对算法本身描述过少,请更具体地说明算法的运作逻辑和方式,如果可以最好给出部分低代码9 v8 x0 `- s# {3 Z(欢迎访问老王论坛:laowang.vip)

9 m) L, F! Y+ K. s8 P: t# X; ?ps:只要做滴好,王爷有赏啊
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2023-12-25 20:19:00 | 显示全部楼层
navebayes 发表于 2023-12-25 20:111 R5 x; I8 ]# b, `/ h" C(欢迎访问老王论坛:laowang.vip)
申请失败,原因:对算法本身描述过少,请更具体地说明算法的运作逻辑和方式,如果可以最好给出部分低代码
! ~& \$ y' Q5 A. ^) [. L5 l) R5 }( m, a& H(欢迎访问老王论坛:laowang.vip)
...

6 L5 f" P% n& o2 u* d1 e. [0 Z我在想怎么算说明运作逻辑.....真贴上去么?这个编辑器到底怎么用啊0 J, P- y  l& f- g8 d2 t- {(欢迎访问老王论坛:laowang.vip)
回复 支持 反对

使用道具 举报

发表于 2023-12-25 20:35:28 手机版 | 显示全部楼层
昔有佳人公孙氏 发表于 2023-12-25 20:25& t7 ^- a( t# ?) d2 h% z: m- W' ~2 k(欢迎访问老王论坛:laowang.vip)
啊这。不如解释一下单源最短路径问题中对于负权值和负权值回路为什么不能使用上述算法! ~6 \4 F* B" P; {# b(欢迎访问老王论坛:laowang.vip)
9 P$ a+ I% G% B" B5 |) j7 X(欢迎访问老王论坛:laowang.vip)
这玩意考试考得头 ...
  D7 n, n) C0 [, K2 Y(欢迎访问老王论坛:laowang.vip)
看作者本人嘛,我不想干涉思路..
0 ?; t) F" R7 ]' s3 M2 d7 S, i/ ]# z% k(程序:哥们这可不是什么负权圈,这是时空之门啊啊啊啊啊(然后获得了每过一年减一岁的黄金体验))
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 20:43:49 | 显示全部楼层
昔有佳人公孙氏 发表于 2023-12-25 20:25  V; j% p; j, c0 C7 {+ S5 d5 v9 b(欢迎访问老王论坛:laowang.vip)
啊这。不如解释一下单源最短路径问题中对于负权值和负权值回路为什么不能使用上述算法
, ?) J* k9 k: L
/ a% D: ]% C- R# i  i- i这玩意考试考得头 ...

! y# U9 c' Z; V: D. p这应该是考专业课考破防了
8 s* c: H) p& x# c# T& f7 d
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 20:48:19 | 显示全部楼层
昔有佳人公孙氏 发表于 2023-12-25 20:25
* b$ d: Y/ _  S& a啊这。不如解释一下单源最短路径问题中对于负权值和负权值回路为什么不能使用上述算法7 X( d1 w: O  [, y3 Y" z(欢迎访问老王论坛:laowang.vip)
7 H) _9 @1 e7 w+ N(欢迎访问老王论坛:laowang.vip)
这玩意考试考得头 ...

, G, |; M/ j! U# P负权不就卡bug了么,越来越低就成环了- k! {% z, r0 H0 S0 W(欢迎访问老王论坛:laowang.vip)
回复 支持 反对

使用道具 举报

发表于 2023-12-25 20:56:03 手机版 | 显示全部楼层
Applcu 发表于 2023-12-25 20:484 O3 X& J2 k9 Q6 n0 [! D! G(欢迎访问老王论坛:laowang.vip)
负权不就卡bug了么,越来越低就成环了

! n/ _& o, L2 e# [& B0 D宝宝,把剩下的内容补上嘛
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 21:15:16 | 显示全部楼层
navebayes 发表于 2023-12-25 20:56( v+ `7 c2 J6 G5 v; ^/ E(欢迎访问老王论坛:laowang.vip)
宝宝,把剩下的内容补上嘛

. p; B% k" L" K. ~9 w真是男童啊.....
$ c4 m% V. J' I" e
回复 支持 反对

使用道具 举报

发表于 2023-12-25 21:37:16 手机版 | 显示全部楼层
Applcu 发表于 2023-12-25 21:157 t2 }$ h! u2 w8 r* a$ G6 [(欢迎访问老王论坛:laowang.vip)
真是男童啊.....

& I6 A" W- f/ B诽谤管理封七天
回复 支持 反对

使用道具 举报

发表于 2023-12-25 22:34:33 | 显示全部楼层
Applcu 发表于 2023-12-25 21:58
: B# X2 @" `; U' \先说说个人对于Dijkstra算法设计地铁线路规划:( ]! r7 G$ {7 G7 ?" r7 h(欢迎访问老王论坛:laowang.vip)
1.首先用爬虫爬到该城市的地铁网络,包含站点名称,该站点 ...

1 C9 b3 w  ^8 q  ]. g可以加入正文喵9 I- {* ?8 B- i6 H  j8 \(欢迎访问老王论坛:laowang.vip)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 22:42:13 | 显示全部楼层
昔有佳人公孙氏 发表于 2023-12-25 20:25
/ n% _+ n3 x3 ~3 x啊这。不如解释一下单源最短路径问题中对于负权值和负权值回路为什么不能使用上述算法
  i% v7 t( ^* c: \0 e( v8 _! A5 |" Z  A; ~1 u0 A. I5 h(欢迎访问老王论坛:laowang.vip)
这玩意考试考得头 ...

8 o$ W  l% k7 H) h2 T我也头大了.....但本质还是因为Dijkstra算法认为,如果有一条最短路线可以直达目的地,那么从旁边走另外的路将会直接不考虑,但在负权边这里,反而会减小cost,所以Dijkstra算法失效了,因为无法发现这条最短的路径
! N, a3 O* d: R2 B0 H7 l; s
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 22:51:56 | 显示全部楼层
navebayes 发表于 2023-12-25 22:34
& J3 U3 Z) X6 f, L! s可以加入正文喵
# Q- B) t& {& X$ q(欢迎访问老王论坛:laowang.vip)
加了加了
6 k/ g6 }4 ~- d0 }
回复 支持 反对

使用道具 举报

发表于 2023-12-25 23:02:44 | 显示全部楼层
Applcu 发表于 2023-12-25 22:51
$ Q' U$ R8 Y% b  q: F+ ^+ Q加了加了
/ Q# Z2 [& E0 q- |(欢迎访问老王论坛:laowang.vip)
介意让我改一下吗https://pic.imgdb.cn/item/6589996fc458853aef070f38.gif
. o0 V0 o: j5 `5 e% C. H/ u7 X' f! E
回复 支持 反对

使用道具 举报

发表于 2023-12-25 23:08:15 | 显示全部楼层
其实目前,本科生能接触到的寻路算法 无外乎迪杰斯特拉和弗洛伊德 一个不吃负值 一个不吃负环
, n# X+ C6 L. g6 P4 ~8 y但其实寻找最短路径的算法里还有很知名的黏菌算法。$ x0 Q4 S/ E2 p0 X9 o! R5 p(欢迎访问老王论坛:laowang.vip)
有兴趣的可以去B站搜搜黏菌走迷宫,看看在大自然顶级的算法编辑下的单源最短路径问题的解法9 y. e. P# M( t: F* W(欢迎访问老王论坛:laowang.vip)
不是说将奖励放置位置对应于日本的各大城市,两天内的黏菌路线就基本和目前日本的城市规划大致相似了吗,当然不太严谨是真的
2 l2 L8 c4 q$ t! a3 [' N; E, p1 i就好像楼主说的做了地铁最短路径规划, 这玩意我舍友和你类似,她做的事全国铁路路径规划,涉及到价格,时间,反正做到最后是你输入起始地址和目的地,就能得出花费最少,时间最少,转站最少的路线,C++课设 我记得很清楚,我记得老师说的评价是,如果再加上运筹学的内容,说不定可以当毕业论文了,不出意外她拿了满分。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 23:30:40 | 显示全部楼层
navebayes 发表于 2023-12-25 23:02( @8 J* Z" p  N1 {(欢迎访问老王论坛:laowang.vip)
介意让我改一下吗

$ b' {8 D5 _" t) K可以可以4 z, [, Q1 ~' Z0 ]2 o% ?(欢迎访问老王论坛:laowang.vip)
回复 支持 反对

使用道具 举报

发表于 2023-12-26 12:03:53 | 显示全部楼层
Applcu 发表于 2023-12-25 23:30) [8 {( X0 I; e- t7 P. \(欢迎访问老王论坛:laowang.vip)
可以可以

; ^$ M4 x+ Z. l' o排版改了下喵,东西加好了喵
% D! g8 `; c& K: A, _. n
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
点击进行验证

本版积分规则

我们不生产资源,只做资源的搬运工。

app下载-tags标签-春满四合院-AvGood-Archiver-小黑屋- |网站地图