一道最短路径 Djkstra(求单源最短路径) 模版题目,不过后期需要搜索处理才能枚举出答案。
完了,普通的DFS试了一发还会超时,需要用记忆化搜索,要保存中间所得的结果,减少递归进行的次数,实际上这个重复递归计算的次数是我们无法想象的大。
记忆化处理过后就AC了!
传送门:HDU-1142-A-Walk-Through-the-Forest
// dj + 记忆化搜索
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int inf = 999999999;
int map[1005][1005];
int dis[1005],vis[1005];
int path[1005];
int n,m;
void Dijkstra(int src) {
int i,j,minn,pos;
memset(vis,0,sizeof(vis));
for(i = 0; i<=n; i++)
dis[i] = map[src][i];
vis[src] = 1;
for(i = 1; i<=n; i++) {
minn = inf;
pos = 0;
for(j = 1; j<=n; j++) {
if(minn > dis[j] && !vis[j])
minn = dis[pos = j];
}
vis[pos] = 1;
for(j = 1; j<=n; j++)
if(dis[j]>dis[pos]+map[pos][j] && !vis[j])
dis[j] = dis[pos]+map[pos][j];
}
}
// 记忆化搜索 - path[] 进行中间结果记忆化
int DFS(int src) {
if(path[src] != -1) // 如果这个点已dfs
return path[src]; // 直接返回这个点的方案数
if(src == 2) // 走到了2点即house
return 1;
path[src] = 0;
for(int i = 1; i<=n; i++) {
// dis[i] < dis[src] i到重点的距离小于src到终点的距离 && 有联通路
// 走到i点
if(dis[i]<dis[src] && map[src][i]!=inf)
path[src] += DFS(i);
}
return path[src];
}
// 不记忆化搜索 会超时间
/*
int DFS(int src) {
if(src == 2) // 走到了2点即house
return 1;
int sum = 0;
for(int i = 1; i<=n; i++) {
if(dis[i]<dis[src] && map[src][i]!=inf)
sum += DFS(i);
}
return sum;
}
*/
int main()
{
int i,j,x,y,z;
while(~scanf("%d",&n),n) {
scanf("%d",&m);
for(i = 0; i<=n; i++) {
for(j = 0; j<=n; j++)
map[i][j] = inf;
map[i][i] = 0;
}
for(i = 0; i<m; i++) {
scanf("%d%d%d",&x,&y,&z);
map[x][y] = map[y][x] = z;
}
// 技巧 : 反过来找2为单源起点的到各个点的最短路径 - 存在 dis[] 数组中
Dijkstra(2);
memset(path,-1,sizeof(path));
printf("%d\n",DFS(1));
}
return 0;
}