您的位置:首页 > Web前端 > JavaScript

poj 2449(A*+dijstra求k短路)

2012-08-30 23:23 260 查看
A*算法入门

A*算法是一种启发式的搜索,不是纯粹的盲目式搜索,A*算法中有个估价算法g(n),对于每个点而言,都有一个g(n)和h(n)来确定的f(n),实际上就是以f(n)为参考权值来确定搜索的方向,在这里,我们的h(n)表示的是从s点出发到n这个点现在走过的路径长度,而g(n)表示的是从n到e的最短长度的大小,那么就确定了搜索的优先性,这里的A*算法的估价函数g(n)是完美估价,搜索的方向一定是对的。

分析:

建图的时候建一个正向的一个反向的,反向的图利用dij求终点到每个点的最短路,即为搜索的估价函数。

注意的地方:

st==en 的时候必须k++ 因为题目要求必须走过路径。

详细见代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define inf 0x7ffffff
#define MAXN 1010
#define MAXM 100005

struct Edge
{
int u;//反向图的终止边
int v;//终止点
int c;//边权值
int next;//下一个节点
int next1;//反向边下一个节点
Edge(){}
Edge(int u,int v,int c):u(u),v(v),c(c){}
}p[MAXM];
int head[MAXN];//链表头
int head1[MAXN];//反向
int e; //邻接表中边总数
int st,en,k;//起点,终点,第k短路
int n,m;
int dis[MAXN];//dis[v]表示的是终点到v的距离,即估价函数g
bool vis[MAXN];

struct pro
{
int v,c;//v是终点,c是起点到v的距离
pro(){}
pro(int v,int c):v(v),c(c){}
bool operator < (const pro& a) const
{
return c+dis[v] > a.c+dis[a.v];//最小值优先队列
}
};

void clear()//初始化
{
memset(head,-1,sizeof(head));
memset(head1,-1,sizeof(head1));
e=0;
}
void addEdge(int u,int v,int c)//加边
{
p[e]=Edge(u,v,c);
p[e].next1=head1[v];head1[v]=e;
p[e].next=head[u];head[u]=e++;
}

priority_queue<pro> que;
void dij(int src)//求估价函数
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=inf;
dis[src]=0;
while(!que.empty())
que.pop();
que.push(pro(src,0));
while(!que.empty())
{
pro cur = que.top();
que.pop();
if(vis[cur.v])
continue;
vis[cur.v]=1;
for(int i=head1[cur.v];i+1;i=p[i].next1)
{
if(dis[p[i].u] > dis[cur.v] + p[i].c)
{
dis[p[i].u] = dis[cur.v] + p[i].c;
que.push(pro(p[i].u,0));
}
}
}
}

int a_star(int src)
{
while(!que.empty())
que.pop();
que.push(pro(src,0));
while(!que.empty())
{
pro cur = que.top();
que.pop();
if(cur.v==en)
{
if(k>1)//相当于求k次最短路
k--;
else
return cur.c;
}

for(int i=head[cur.v];i+1;i=p[i].next)//将所有与u相连接的点都加入队列
que.push(pro(p[i].v,cur.c+p[i].c));
}
return -1;
}

int main()
{
int u,v,c;
while(scanf("%d%d",&n,&m) != EOF)
{
clear();
while(m--)
{
scanf("%d%d%d",&u,&v,&c);
addEdge(u,v,c);
}
scanf("%d%d%d",&st,&en,&k);
dij(en);
if(dis[st]==inf)
{
puts("-1");
continue;
}
if(st == en)
k++;
printf("%d\n",a_star(st));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: