题目链接http://www.zybbs.org/JudgeOnline/problem.php?id=1579
某小朋友给的题,无奈不会做。T T。后来一问知道是用动态规划,搜了下,感觉好神奇。
两种方法,一种是建立层次图,然后求最短路即可。(这个层次图特点是,把所有可能路径(包括任何一条边为0,感觉好神奇)都覆盖掉),见http://hi.baidu.com/lrc2222/blog/item/e40177f76c37b338720eecc7.html
第二种方法就是动态规划了,不过这个动归和本层的有关系,开始很郁闷,想着,难道要用搜索么。。。后来看人家说的,大悟,可以用最短路dijkstra的思想,不断找最小的点去更新还没有被赋值的点。用普通的DIJKSTRA超时了,换成加优先队列的A掉。见http://hi.baidu.com/lxxstar1226/blog/item/0c850ddc5eba4f1e62279875.html
顺便好好学习了下以前对优先队列的误区。。。T T。。。以前一直不会写那个如果只有int的比较函数怎么写。。
#include <queue> #include <stack> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <limits.h> #include <string.h> #include <string> #include <algorithm> using namespace std; const int MAX = 10010; struct NODE{int to,len;NODE *next;}; NODE *p[MAX],node[MAX*10]; int cou; int dis[25][MAX],L; void init() { cou = 0; memset(node,'\0',sizeof(node)); memset(p,'\0',sizeof(p)); } void Add(int x,int y,int w) { node[cou].len = w; node[cou].to = y; node[cou].next = p[x]; p[x] = &node[cou++]; } struct cmp{ bool operator()(int a,int b) { return dis[L][a] > dis[L][b]; } }; void Dijkstra(int s,int n,int *dis) { bool used[MAX]; memset(used,0,sizeof(used)); used[s] = true; dis[s] = 0; int now = s; for(int i=0; i<n-1; i++) { NODE *head = p[now]; while( head ) { if( dis[head->to] > dis[now] + head->len ) dis[head->to] = dis[now] + head->len; head = head->next; } int mmin = INT_MAX; for(int k=1; k<=n; k++) if( !used[k] && mmin > dis[k] ) mmin = dis[now = k]; used[now] = true; } } void Dijkstra1(int s,int n,int l) { priority_queue<int,vector<int>,cmp> q; bool used[MAX]; memset(used,0,sizeof(used)); used[s] = true; int now = s; dis[l][s] = 0; q.push(s); while( !q.empty() ) { int now = q.top(); used[now] = true; NODE *head = p[now]; q.pop(); while( head ) { if( dis[l][head->to] > min( dis[l-1][now],dis[l][now] + head->len ) ) { dis[l][head->to] = min( dis[l-1][now],dis[l][now] + head->len ); q.push(head->to); } head = head->next; } } } int main() { int n,m,K,x,y,w; while( ~scanf("%d%d%d",&n,&m,&K) ) { while( m-- ) { scanf("%d%d%d",&x,&y,&w); Add(x,y,w); Add(y,x,w); } for(int k=0; k<=K; k++) for(int i=1; i<=n; i++) dis[k][i] = 500000000; Dijkstra(1,n,dis[0]); for(L=1; L<=K; L++) Dijkstra1(1,n,L); printf("%d\n",dis[K][n]); } return 0; }