poj2449 Remmarguts' Date A*搜索

来源:互联网 发布:linux查看服务器ip 编辑:程序博客网 时间:2024/05/13 14:10

A*搜索主要思想:f[i] = g[i] + h[i] 。f[i] 即为所求,g[i] 表示已走过距离,h[i] 表示距离终点的距离。在优先队列中,能尽量把符合条件的方案提前,优化搜索。

对于这道题,先反向建边,求出每个点到终点的最短距离。

再正向搜索,所要记录的内容有:当前节点,已走过了距离,已走过的距离+这点到终点的距离。

每次把与这点相连的下一个点放入队列,直到第k次取出终点,便求出第k短路。

注意:自己到自己距离为0不算(坑爹)。

#include<stdio.h>#include<string.h>#include<queue>#include<algorithm>using namespace std;#define inf 100010#define INF 0xffffffstruct node1{int to,next,val;};node1 edge1[inf],edge2[inf];int cnt1;int head1[1010];void add1(int f,int t,int v){edge1[cnt1].to=t;edge1[cnt1].val=v;edge1[cnt1].next=head1[f];head1[f]=cnt1++;}int cnt2;int head2[1010];void add2(int f,int t,int v){edge2[cnt2].to=t;edge2[cnt2].val=v;edge2[cnt2].next=head2[f];head2[f]=cnt2++;}int n,m,s,t,k;int vis[1010],dis[1010];void spfa(){for(int i=1;i<=n;i++){dis[i]=INF;vis[i]=0;}queue<int>Q;Q.push(t);dis[t]=0;vis[t]++;while(!Q.empty()){int u=Q.front();Q.pop();vis[u]--;if(vis[u]>n)return ;for(int i=head1[u];i!=-1;i=edge1[i].next){int v=edge1[i].to;if(dis[v]>dis[u]+edge1[i].val){dis[v]=dis[u]+edge1[i].val;if(vis[v]==0){vis[v]++;Q.push(v);}}}}return ;}struct node{int i,len,sum;bool operator<(const node &r ) const  //这个必须放在里面,尽管我不知道为什么。。。就因为这个,我把poj刷屏了。。。坑了爹一晚上啊!!!    {          if(r.sum==sum)              return r.len<len;          return r.sum<sum;      }};int cnt;int bfs(){priority_queue<node>QQ;if(s==t)k++;//因为自己到自己距离为0不算if(dis[s]==INF)return -1;node st;st.i=s;st.len=0;st.sum=dis[s];QQ.push(st);while(!QQ.empty()){node u;u=QQ.top();QQ.pop();if(u.i==t){cnt++;}if(cnt==k){return u.len;}for(int j=head2[u.i];j!=-1;j=edge2[j].next){node v;v.i=edge2[j].to;v.len=u.len+edge2[j].val;v.sum=v.len+dis[v.i];QQ.push(v);}}return -1;}int main(){memset(head1,-1,sizeof(head1));memset(head2,-1,sizeof(head2));scanf("%d %d",&n,&m);for(int i=1;i<=m;i++){int a,b,c;scanf("%d %d %d",&a,&b,&c);add1(b,a,c);add2(a,b,c);}scanf("%d %d %d",&s,&t,&k);spfa();printf("%d\n",bfs());}


0 0