HDU 1428 漫步校园 特殊的最短路

Posted alking1001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1428 漫步校园 特殊的最短路相关的知识,希望对你有一定的参考价值。

HDU 1428 漫步校园 特殊的最短路

题意

这里需要读懂题意中的一句话“另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一条从A到机房的路线更近(否则可能永远都到不了机房了…)。”

这句话的意思是从(1, 1)(n, n)的所有路径中,只选择距离最短的路径,并输出最短路径的条数。就是我们找出最短距离后,看看有多少条路到达目的地是最短距离。

解题思路

从题意我们也就知道了,我们需要找出每个点到目的地的最短路是多少。这里我们最先想到的就是一些最短路的算法了,比如Dijkstra算法,需要注意的是这里的图形是一个矩阵,而不是普通的那种图,所以这里的最短路算法和常见的最短路算法有些不同,这里的bfs函数其实也是使用的这个最短路算法的思想,也是找出一个点来进行松弛。

还有需要注意点的是我们要倒过来进行最短路的计算,计算从(n, n)到其他各个点的最短路径。为什么要这样呢?因为我们的算法是单源最短路,我们需要知道所有的点到终点的最短路,如果是从(1, 1)开始计算,我们得到的是从(1,1)到各个点的最短路经,思路反过来就能解决,真神奇!

接下来我们就要计算出有多少条路了,如果没有要求的话,最容易想到的是可以使用dfs来计算出路径的种类,这里我也是这样做的,但是这个题有条件,每一步只能最近的路,上面我们已经知道了每个点到终点的最短距离了,我们使用dfs进行拓展的时候可以判断我们要走的下一个点是不是最优的那个点(注意,可能下一步的最优点可能由多个),其实就是多了个条件判断,很有意思。

下们就是实现的代码。

代码实现

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
typedef long long ll;
using namespace std;
const double esp=1e-6;
const int inf=0x3f3f3f3f;
const int MAXN=50+7;
struct node{
	int x, y;
	node(){}
	node(int a, int b){
		x = a;
		y = b;
	}
};
int gox[4] = {-1, 1, 0, 0}; //上下左右
int goy[4] = {0, 0, -1, 1}; 
int mp[MAXN][MAXN], dis[MAXN][MAXN];
ll road[MAXN][MAXN];
bool vis[MAXN][MAXN];
int n;
void bfs(){//找点(n, n)到其他点的最短距离 
	vis[n][n] = 1;
	dis[n][n] = mp[n][n];
	queue<node> que;
	que.push(node(n, n));
	while(!que.empty())
	{
		node cur = que.front();
		que.pop();
		vis[cur.x][cur.y] = 0;
		for(int i=0; i<4; i++)
		{
			node nt(cur.x + gox[i], cur.y + goy[i]);
			if(nt.x < 1 || nt.x > n || nt.y < 1 || nt.y > n)
				continue;
			if(dis[nt.x][nt.y] > dis[cur.x][cur.y] + mp[nt.x][nt.y]){
				dis[nt.x][nt.y] = mp[nt.x][nt.y] + dis[cur.x][cur.y];
				if(!vis[nt.x][nt.y]){
					vis[nt.x][nt.y] = 1;
					que.push(node(nt.x, nt.y));
				}
			} 
		}
	} 
}
ll dfs(int x, int y)
{
	if(x == n && y == n)
		return 1;
	if(road[x][y] != -1)
		return road[x][y];
	road[x][y] = 0;
	int ntx, nty;
	for(int i=0; i<4; i++)
	{
		ntx = x + gox[i];
		nty = y + goy[i];
		if(ntx < 1 || ntx > n || nty < 1 || nty > n || dis[ntx][nty] >= dis[x][y])
			continue;
		road[x][y] += dfs(ntx, nty);
	}
	return road[x][y];
}
int main()
{
	while(cin>>n)
	{
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++){
				cin>>mp[i][j];
				road[i][j] = -1;
                dis[i][j] = inf;
				vis[i][j] = 0;
			}	
		bfs();
		cout<<dfs(1, 1)<<endl;
	}
	return 0;
}

以上是关于HDU 1428 漫步校园 特殊的最短路的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 1428bfs+记忆化

hdu 6166 Senior Pan

选择合适的最短路--hdu3499

HDU 2157 How many ways??

HDU 5294 Tricks Device (最大流+最短路)

C - 最短路径问题 (HDU - 3790 )