zoukankan      html  css  js  c++  java
  • HDU 1142 A Walk Through the Forest(Dijkstra+Dfs(第一次用记忆化搜索))

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1142

    题意:这题的题意很重要,起点是1,终点是2,现在主人公已经知道,所有边的长度,然后他开始选择走不走某条边了。。

    对于图中的每条边(A,B),他选这条边的前提是:存在一条B到终点的路径,比所有从A道终点的路径都短(即只要B到2的最短路径比A到2的最短路径短就存在了),选择完所有可以走的边后,问一共有多少条从1到2的路径

    因为对于每条边(A,B)都要知道A到2的最短路和B到2的最短路,对于每个点都用Dijkstra的话O(n^3)超时,注意到,每次都是和2的最短路,所以灵活点,以2为起点用以次Dijkstra就可以求出所有结果。

    然后用深搜,搜出所有的边,但是会超时,所以要用到记忆化搜索,要用辅助数组来保存结果,ans[now]表示now到终点一共有多少条路。开始初始化为0。。。。。由于某个点,可能有多条路经过,用了记忆化搜索,当不是第一次经过的时候,ans[now]已经有答案了。。。。要特别注意的是这里其实根本不需要用vis[]来标记有每走过,ans[now]已经记录了有每走过了。。。。。。。这里跟Dfs中for里vis[]区分开来。。。。。

    记忆化搜索是为了避免重复做同一件事(这题是为了避免重复计算某点到终点的路径数)

    而,深搜for里的vis[]是为了当从另一条路经过该点时能够经过。。

    代码:

    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int M = 1111;
    const int INF = 1 << 30;
    
    int d[M];
    int g[M][M];
    bool used[M];
    //bool vis[M];
    int ans[M];
    int compare;
    int n, m;
    
    
    
    //vector <int> gg[1010];
    
    
    void D(int star)//记录所有到2的最短路径
    {
        for (int i = 1; i <= n; i++)
        {
            d[i] = INF;
        }
        memset(used, 0, sizeof(used));
    
        d[star] = 0;
        for (int cnt = 0; cnt < n; cnt++)
        {
            int  min = INF;
            int min_num = 0;
            for (int i = 1; i <= n; i++)
            {
                if (!used[i] && min > d[i])
                {
                    min = d[i];
                    min_num = i;
                }
            }
    
            used[min_num] = 1;
    
            for (int i = 1; i <= n; i++)
            {
                if (!used[i] && d[i] > d[min_num] + g[min_num][i])
                {
                    d[i] = d[min_num] + g[min_num][i];
                }
            }
    
        }
    }
    
    
    int Dfs(int now)
    {
        if (ans[now])
        {
            return ans[now];
        }
        if (now == 2)
        {
            return 1;
        }
    
        for (int i = 1; i <= n; i++)
        {
            if (/*!vis[i]  && */g[now][i] != INF && d[now] > d[i])
            {
                
                ans[now] += Dfs(i);
            }
        }
        return ans[now];
    }
    
    
    int main()
    {
        
    
        while (scanf("%d", &n), n)
        {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                g[i][j] = INF;
            }
        }
    
            scanf("%d", &m);
                    
            while (m--)
            {
                int a, b, c;
                scanf("%d%d%d", &a, &b, &c);
    
                g[a][b] = g[b][a] = c;
            }
    
            D(2);
            memset(ans, 0, sizeof(ans));//ans[i]表示i道终点路径的条数
            //memset(vis, 0, sizeof(vis));
            //vis[1] = 1;
            printf("%d\n", Dfs(1));
        }
        return 0;
    }
  • 相关阅读:
    DAO模式多表联查
    使用ADO.NET访问数据库
    连接查询和分组查询
    模糊查询和聚合函数
    poj 1220 NUMBER BASE CONVERSION
    poj 1964 City Game
    Odd number problem
    POJ 2983 M × N Puzzle
    L O V E
    【Mybatis】【3】处理大于号小于号及其他特殊字符
  • 原文地址:https://www.cnblogs.com/qiufeihai/p/2658557.html
Copyright © 2011-2022 走看看