• 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;
    }
    
  • 相关阅读:
    docker镜像
    docker常用命令
    docker基础
    跨站脚本漏洞(XSS)基础
    Session、Cookie与Token
    linux之curl工具
    ssl证书与java keytool工具
    mysql主从复制
    linux之平均负载(学习笔记非原创)
    mysql8.0忘记密码如何操作?
  • 原文地址:https://www.cnblogs.com/alking1001/p/12559256.html
Copyright © 2020-2023  润新知