题目链接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;
}