hdu 1142 最短路+记忆化

最短路+记忆化搜索
HDU 1142 A Walk Through the Forest
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1142

> 题意:找出不同的路径条数,假如jimmy要从A走到B的话满足jimmy从B到家的距离比从A到家的距离短
> 这样我们可以通过最短路算法,找出从家(看成源点)到各个点的最短路径长度,记做D[v]。 然后就可以从起点(office)
> dfs,首先从某点i到某点j走得通,然后满足D[j]<D[j],则可以往下搜索,直到终点(house),普通的dfs是会超时的,N都是1000了,不加剪枝啥的,dfs生成树那么大,肯定会TLE的。
> 所以这里要用记忆话搜索,减少重复计算某个一个状态的值。 对于最短路和记忆化,本人也是刚刚学习的,最短路模仿的数据结构书上的
> dijkstra,记忆化也是借鉴别人的思路。不过我想说说子结构的重复计算 比如 0
> 1 2
> 3 4 5 6

> 7 8 9

>  10   dfs(0) 是 从0到10的所以路径条数(假设走法随意,只要深度+1即可) dfs(4)是从4到10的路径条数,1可以到4,2也可以到4.
> 那么dfs(1)后肯定已经计算过dfs(4)了,dfs(2)就没必要再计算,直接用这个结果就行了 所以可以用个数组保存即可
> 再啰嗦一句,题库分这题在并查集里面,有哪位大神能教我并查集怎么做?

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef struct
{
    int arcs[1010][1010];
    int vexnum,arcnum;
    int vexs[1010];
} AMGraph;
AMGraph G;
int D[1010],path[1010],S[1010],dp[1010];///这里忽略掉path吧,没用到
const int maxint = 1000000000;
int n,m;
void createG(AMGraph &G)
{
    int x,y,distance;
    for(int i = 1 ; i <=n; i++)
        for(int j =1; j<=n; j++)
            G.arcs[i][j] = maxint; ///建图,不连通的用一个能够满足题意的无穷大值表示
    for(int i = 0; i<m; i++)
    {
        scanf("%d%d%d",&x,&y,&distance);
        G.arcs[x][y] = G.arcs[y][x] = distance;
    }
}
void shortestflyod(AMGraph &G,int v0)///书上代码,不懂得还是看书吧
{
    int v,w;
    for( v = 1; v<=n; v++)
    {
        S[v] = 0;
        D[v] = G.arcs[v0][v];
        if(D[v]<maxint) path[v] = v0;
        else path[v] = -1;
    }
    S[v0] = 1;
    D[v0] = 0;
    for(int i =2 ; i<=n; i++)
    {
        int minn = maxint;
        for( w = 1; w<=n; w++)
            if(!S[w]&&D[w]<minn)
            {
                v = w;
                minn = D[w];
            }
        S[v] = 1;
        for(w = 1; w<=n; w++)
            if(!S[w]&&D[v]+G.arcs[v][w]<D[w])
            {
                D[w] = D[v] + G.arcs[v][w];
                path[w] = v;
            }
    }
}
int  dfs(int v)
{
    if(v==2)///到终点,找到一条路径
    {
        return 1;
    }
    if(dp[v]) return dp[v];///计算过,直接返回
    for(int i = 1; i<=n; i++)
        if(G.arcs[v][i]!=maxint&&D[i]<D[v])//连通且满足条件
            dp[v] += dfs(i);//dp[v] 等于下面一个分支的路径数之和
    return dp[v];
}
int main()
{
    while(scanf("%d",&n)&&n)
    {
        scanf("%d",&m);
        createG(G);
        shortestflyod(G,2);
        memset(dp,0,sizeof(dp));
        int ans = 0;
        ans = dfs(1);
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jiachinzhao/p/4547873.html