K短路-有环版

写了一个基于A*的最朴素算法,由于对A*的原理,启发函数之类的没有什么详细的学习,只有一个大概的了解。

算法的思路再抛开A*原理(就是假装我懂了)后是很好理解的。

朴素的算法用每个点到汇点的最短路作为估价函数,所以就是在先用dijkstra预处理出最短路,然后作为估价函数。

p.s.这个A*比八数码好写多了……

贴一下我的模板,如有错误之处欢迎大家指正

ContractedBlock.gif ExpandedBlockStart.gif k-shortest-path
 
   
1 /* 估价函数f(x) = g(x) + h(x);
2 * h(x) = h*(x);所以符合A*条件
3 * 本代码所求得的k短路含环
4 * status中f为A*的估价函数。更新为
5 * f(x2)=f(x1)-h(x1)+h(x2)+c(x1)(x2);
6 */
7 #include < iostream >
8 #include < cstring >
9 #include < cstdio >
10 #include < queue >
11 using namespace std;
12 const int V = 1000 ;
13 const int E = 100000 ;
14 const int INF = 100000000 ;
15
16 struct status
17 {
18 int v, f;
19 status(){}
20 status( int _v, int _f)
21 {
22 v = _v, f = _f;
23 }
24 bool operator < ( const status a) const
25 {
26 return f > a.f;
27 }
28 };
29
30 struct edge
31 {
32 int v, dist;
33 edge * nxt;
34 } * pp, * g[V], * rg[V], pool[E * 2 ];
35 int d[V], c[V];
36 bool chk[V];
37 void initialize()
38 {
39 pp = pool;
40 memset(g, 0 , sizeof (g));
41 memset(rg, 0 , sizeof (rg));
42 }
43
44 void addedge( int u, int v, int dist, edge * g[])
45 {
46 pp -> v = v;
47 pp -> dist = dist;
48 pp -> nxt = g[u];
49 g[u] = pp ++ ;
50 }
51
52 void dijkstra( int n, int t)
53 {
54 fill(d, d + n, INF);
55 memset(chk, false , sizeof (chk));
56 priority_queue < status > pq;
57 pq.push(status(t, 0 ));
58 while ( ! pq.empty())
59 {
60 status now = pq.top();
61 pq.pop();
62 if (chk[now.v])
63 continue ;
64 chk[now.v] = true ;
65 d[now.v] = now.f;
66 for (edge * i = rg[now.v]; i != NULL;i = i -> nxt)
67 pq.push(status(i -> v, now.f + i -> dist));
68 }
69 }
70
71 int Astar( int s, int t, int k)
72 {
73 if (d[s] == INF)
74 return - 1 ;
75 memset(c, 0 , sizeof (c));
76 priority_queue < status > pq;
77 pq.push(status(s, d[s]));
78 while ( ! pq.empty())
79 {
80 status now = pq.top();
81 pq.pop();
82 c[now.v] ++ ;
83 if (c[t] == k)
84 return now.f;
85 if (c[now.v] > k)
86 continue ;
87 for (edge * i = g[now.v]; i != NULL; i = i -> nxt)
88 {
89 pq.push(status(i -> v, now.f - d[now.v] + d[i -> v] + i -> dist));
90 }
91 }
92 return - 1 ;
93 }
94
95 int main()
96 {
97 int n, m, s, t, k;
98 int u, v, dist;
99 while (scanf( " %d %d " , & n, & m) == 2 )
100 {
101 initialize();
102 for ( int i = 0 ;i < m;i ++ )
103 {
104 scanf( " %d %d %d " , & u, & v, & dist);
105 u -- , v -- ;
106 addedge(u, v, dist, g);
107 addedge(v, u, dist, rg);
108 }
109 scanf( " %d %d %d " , & s, & t, & k);
110 s -- , t -- ;
111 if (s == t)
112 k ++ ;
113 dijkstra(n, t);
114 printf( " %d\n " , Astar(s, t, k));
115 }
116 return 0 ;
117 }

POJ 2449的代码 280多MS AC,效率不是很高,还需要学新的算法

YEN氏算法的效率比较高的说,无环版的也有待考虑

转载于:https://www.cnblogs.com/ronaflx/archive/2011/03/02/1968904.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值