欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

2011年北京大学计算机研究生机试真题(dijkstra+优先队列)

发布时间:2024/7/19 编程问答 83 豆豆
生活随笔 收集整理的这篇文章主要介绍了 2011年北京大学计算机研究生机试真题(dijkstra+优先队列) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

http://ac.jobdu.com/problem.php?pid=1162  I Wanna Go Home

方法一:普通的dijkstra

/* 很明显的最短路,但关键是如何建图。可以看到,一共只有两种走法,一种是从city1出发,一直走属于group1的city直到city2,或者一直走属于group2的city直到city1。我昨天建了两个图来表示两种情况,分别求最短路,然后取小的,结果越写越乱。今天发现其实一次就可以,只要在建图的时候,如果两个city属于一个group,就建双向图,否则就建从属于group1的city到属于group2的city的单向图。原因很简单,因为两种情况都不会出现从2到1的情况。建好图然后就简单了,注意无解的情况。 */ #include<iostream> #include<cstdio> using namespace std; #include<memory.h>int map[601][601],x[601]; int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数 {int visit[601]; //判断是否已存入该点到visit集合中int i,j,k,min,t;for (i=1;i<=n;i++){x[i]=map[start][i];visit[i]=0; //初始都未用过该点}x[start]=0;visit[start]=1;// 依次将未放入visit集合的结点中,取x[]最小值的结点,放入集合visit中// 一旦visit包含了所有顶点,x就记录了从源点到所有其他顶点之间的最短路径长度// 注意是从第二个节点开始,第一个为源点for(i=2;i<=n;i++){min = 16843009;t=-1;// 找出当前未使用的点j的x[j]最小值for(j=1; j<=n; ++j){if(!visit[j] && x[j]<min){t = j; // t保存当前邻接点中距离最小的点的号码min = x[j];}}if(t!=-1){visit[t] = 1; // 将t点存入visit集合中// 更新x的值for(j=1; j<=n; ++j){if (!visit[j] && min+map[t][j]<x[j])x[j]=min+map[t][j];}}}if(x[end]<16843009)return x[end];elsereturn -1; } int main(void) {int i,j,n,m,from,to,cost,group[601];while(scanf("%d",&n),n){scanf("%d",&m);for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(i==j)map[i][j]=0;elsemap[i][j]=16843009;}}//memset(map,1,sizeof(map));for(i=0;i<m;i++){scanf("%d %d %d",&from,&to,&cost);if(cost<map[from][to])map[from][to]=map[to][from]=cost;}for(i=1;i<=n;i++)scanf("%d",&group[i]);for(i=1;i<n;i++){for(j=i+1;j<=n;j++){if(group[i]==group[j]) //如果是一个group,不用管continue;else if(group[i]==1 && group[j]==2) //如果一个是1一个是2,则建单向边 map[j][i]=16843009;else if(group[i]==2 && group[j]==1) //如果一个是1一个是2,则建单向边 map[i][j]=16843009;}}printf("%d\n",dijkstra(n,1,2));}return 0; }

 方法二:优先队列+邻接表 来实现dijkstra算法

/* 优先队列+邻接表 来实现dijkstra算法 根据下面的那个模板来修改过来的 */ #include<iostream> #include<cstdio> #include<queue> using namespace std; #include<memory.h>#define INF 16843009 #define MAXN 601 //结点的个数typedef struct Edge {int adj;struct Edge *next;int cost; }Edge,*pEdge; Edge edge[MAXN];typedef struct Heap {bool operator <(Heap T)const{return T.dis<dis;}int x;int dis; }Heap;struct Node {int from,to,cost; }node[10001];void insert_adjlist(int a,int b, int c) //创建邻接表 {pEdge p,q;p=&edge[a]; while(p->next!=NULL)p=p->next;q=new Edge;q->adj=b;q->next=NULL;q->cost=c;p->next=q; }int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数 {int i,x[MAXN];bool visit[MAXN];Heap cur,in;pEdge p;memset(visit,false,sizeof(visit));for(i=1;i<=n;i++)x[i]=INF;priority_queue< Heap >q; //优先级队列cur.x=start;cur.dis=0;x[start]=0;q.push(cur);while(!q.empty()){cur = q.top();q.pop();if(cur.x == end) //找到终点return cur.dis;if(visit[cur.x]) //访问过continue;visit[cur.x]=true;p=edge[cur.x].next;while(p!=NULL){if(!visit[p->adj]){in.x=p->adj;in.dis=cur.dis+p->cost;if(in.dis<x[in.x]){x[in.x]=in.dis;q.push(in);}}p=p->next;}}return -1; }int main(void) {int i,j,n,m,from,to,group[601];while(scanf("%d",&n),n){scanf("%d",&m);for(i=1;i<=n;i++)edge[i].next=NULL;for(i=0;i<m;i++){scanf("%d %d %d",&node[i].from,&node[i].to,&node[i].cost); //暂时保存起来}for(i=1;i<=n;i++)scanf("%d",&group[i]);for(i=0;i<m;i++){from=node[i].from;to=node[i].to;if(group[from]==group[to]) //如果是一个group,建立双向边{insert_adjlist(from,to,node[i].cost);insert_adjlist(to,from,node[i].cost); }else if(group[from]==1 && group[to]==2) //如果一个是1一个是2,则建单向边insert_adjlist(from,to,node[i].cost);else if(group[from]==2 && group[to]==1) //如果一个是1一个是2,则建单向边insert_adjlist(to,from,node[i].cost); }printf("%d\n",dijkstra(n,1,2));}return 0; }

http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路

//优先队列+邻接表 来实现dijkstra算法(模板) #include<iostream> #include<cstdio> #include<queue> using namespace std; #include<memory.h>#define INF 16843009 #define MAXN 601 //结点的个数typedef struct Edge {int adj;struct Edge *next;int cost; }Edge,*pEdge; Edge edge[MAXN];typedef struct Heap {bool operator <(Heap T)const{return T.dis<dis;}int x;int dis; }Heap;void insert_adjlist(int a,int b, int c) //创建邻接表 {pEdge p,q;p=&edge[a]; while(p->next!=NULL)p=p->next;q=new Edge;q->adj=b;q->next=NULL;q->cost=c;p->next=q; }int dijkstra(int n,int start,int end) //start是原点,n是图中所有点的个数 {int i,x[MAXN];bool visit[MAXN];Heap cur,in;pEdge p;memset(visit,false,sizeof(visit));for(i=1;i<=n;i++)x[i]=INF;priority_queue< Heap >q; //优先级队列cur.x=start;cur.dis=0;x[start]=0;q.push(cur);while(!q.empty()){cur = q.top();q.pop();if(cur.x == end)return cur.dis;if(visit[cur.x])continue;visit[cur.x]=true;p=edge[cur.x].next;while(p!=NULL){if(!visit[p->adj]){in.x=p->adj;in.dis=cur.dis+p->cost;if(in.dis<x[in.x]){x[in.x]=in.dis;q.push(in);}}p=p->next;}}return -1; }int main(void) {int i,j,n,m,from,to,cost,group[601];while(scanf("%d %d",&n,&m),n+m){for(i=1;i<=n;i++)edge[i].next=NULL;for(i=0;i<m;i++){scanf("%d %d %d",&from,&to,&cost);insert_adjlist(from,to,cost);insert_adjlist(to,from,cost); }printf("%d\n",dijkstra(n,1,n));}return 0; }

总结

以上是生活随笔为你收集整理的2011年北京大学计算机研究生机试真题(dijkstra+优先队列)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。