HDU--1142--A Walk Through the Forest--深广搜/DP/最短路径/记忆化搜索

A Walk Through the Forest

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5948    Accepted Submission(s): 2191


Problem Description
Jimmy experiences a lot of stress at work these days, especially since his accident made working difficult. To relax after a hard day, he likes to walk home. To make things even nicer, his office is on one side of a forest, and his house is on the other. A nice walk through the forest, seeing the birds and chipmunks is quite enjoyable.
The forest is beautiful, and Jimmy wants to take a different route everyday. He also wants to get home before dark, so he always takes a path to make progress towards his house. He considers taking a path from A to B to be progress if there exists a route from B to his home that is shorter than any possible route from A. Calculate how many different routes through the forest Jimmy might take.
 

Input
Input contains several test cases followed by a line containing 0. Jimmy has numbered each intersection or joining of paths starting with 1. His office is numbered 1, and his house is numbered 2. The first line of each test case gives the number of intersections N, 1 < N ≤ 1000, and the number of paths M. The following M lines each contain a pair of intersections a b and an integer distance 1 ≤ d ≤ 1000000 indicating a path of length d between intersection a and a different intersection b. Jimmy may walk a path any direction he chooses. There is at most one path between any pair of intersections.
 

Output
For each test case, output a single integer indicating the number of different routes through the forest. You may assume that this number does not exceed 2147483647
 

Sample Input
 
   
5 6 1 3 2 1 4 2 3 4 3 1 5 12 4 2 34 5 2 24 7 8 1 3 1 1 4 1 3 7 1 7 4 1 7 5 1 6 7 1 5 2 1 6 2 1 0
 

Sample Output
 
   
2 4
 

题意:和HDU1978一样的题目,只不过那里的是给的地图,这里是给的稀疏矩阵,给你M组输入信息a,b,c表示a到b距离为c,求从1到2的路线数,要求:A能走向B的前提是B到2的最短路比A短

解析:也没什么好说的,从2做出到达每点的最短距离,然后从1开始按照这个距离递减去搜索



#include 
#include 
#include 
#define Max 2147483648
using namespace std;
int n,dd[4][2]={0,1,0,-1,1,0,-1,0};
__int64 m,dp[1111],dis[1111],mm[1111][1111];//要用64位,不然2147483648会出错的
int vis[1111];
void dj()//djkstra算法,迪杰斯特拉
{
    int i,j,k,l;
    __int64 Min;
    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
    dis[i]=mm[2][i];
    dis[2]=0;
    for(i=1;i<=n;i++)
    {
        Min=Max;
        for(j=1;j<=n;j++)	//从没有访问过的点中找距离2最近的
        if(vis[j]==0&&Min>dis[j])
        {
            Min=dis[j];	//记录最小值
            l=j;	//记录下标
        }
        if(Min==Max)break;	//如果没有找到就结束
        vis[l]=1;	//标记这一点已经访问
        for(j=1;j<=n;j++)	//用这个最近的点去更新其他点,这一步的术语叫做松弛
        {
            if(dis[j]>dis[l]+mm[l][j])	//松弛
            {
                dis[j]=dis[l]+mm[l][j];
            }
        }
    }
}
__int64 dfs(int x)//按照先前求出的最短路径值递减去搜索
{
    int i,j,k,l;
    if(dp[x])return dp[x];	//记忆化搜索的操作,避免重复搜
    for(i=1;i<=n;i++)
    if(mm[x][i]<Max&&dis[i]<dis[x])	//记住在判断最短路径值的同时一定要确定这两点之间有路
    {
        dp[x]+=dfs(i);
    }
    return dp[x];
}
int main (void)
{
    int i,j,k,l,a,b;
    __int64 c;
    while(~scanf("%d",&n)&&n)
    {
        scanf("%I64d",&m);
        memset(mm,0,sizeof(mm));
        for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        mm[i][j]=Max;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%I64d",&a,&b,&c);
            if(mm[a][b]>c)	//因为没看题,所以不确定有没有重边,反正这样写了不会错咯
            mm[a][b]=mm[b][a]=c;
        }
        dj();
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        dp[2]=1;
        dfs(1);
        printf("%I64d\n",dp[1]);
    }
    return 0;
}

总结:越写越顺了,对写记忆化搜索也越来越有手感了,感觉跟妹子拉手一样,根本停不下来啊



你可能感兴趣的:(DP,最短路,深搜)