hdu 1142 A Walk Through the Forest

A Walk Through the Forest

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


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

Source

Recommend
Eddy

第一次做最短路问题的题,查了不少了资料。看了不少的算法知识。终于还是做出来了。呵呵。

#include <stdio.h>
#include<string.h>
int INF=240000000;//定义一个无穷大数
int dis[1010][1010],d[1010],w[1010],mode[1010];
//dis存两个路口间的距离。d存从起点到终点距离。倒着走的。结果一样。因为起点和终点只有一个
//w记录到i号路口有多少满足条件的路。mode记录剩下的路口是否有比该路口更接近起点的
//1代表没有了
int n,m;

void init()//初始化
{
    int i,j;
    memset(w,-1,sizeof w);
    memset(mode,0,sizeof mode);
   // memset(d,INF,sizeof d);//试过这个但这样不行不知道为什么
    for(i=1;i<=n;i++)
    {
        d[i]=INF;
        for(j=1;j<=n;j++)
            dis[i][j]=INF;//若两个路口之间没有路那么他们之间的路程就为无穷远。可以用来
                         //判断两个路口之间有没有路
    }
}
void dp()
{
    int i,j,nmin,p=0;//p记录当前到起点最近的路口号。
    //nmin记录
    d[2]=0;//初始2为起点。所以2到起点距离为0;

    for(j=1; j<=n; j++)//一次删除一个结点。所以需要n*n次走完
    {
        nmin=INF;
        p=0;
        for(i=1; i<=n; i++)//找到到起点最近的路口
        {
            if(mode[i]!=1&&d[i]<nmin)
                nmin=d[i],p=i;
        }
        mode[p]=1;//确定是最小后删除。遍历后是最小的。说明已经走过的点到起点
            //距离比该点到起点距离都大。若其他点若再走到该点其离起点距离肯定更大。
        for(i=1; i<=n; i++)
        {
            //贪心加动态规划
            if(mode[i]!=1&&d[p]+dis[p][i]<d[i])//如果i路口到起点还不是最近还不是如果从p路口能够到i路口。
                d[i]=d[p]+dis[p][i];//如果起点到i路口有更短距离记录从p路口到i路口的距离
        }
    }
}
int dfs(int s)//递归找出满足条件的路
{
    if(s==2)
        return 1;
    if(w[s]!=-1)//记忆化搜索
        return w[s];
    int sum=0;
    int i;

    for(i=1;i<=n;i++)
    {
        if(dis[i][s]!=INF&&d[i]<d[s])//朝着离家越来越近的路走
            sum+=dfs(i);
    }
    w[s]=sum;
    return w[s];
}
int main()
{
    int i,a,b,ds;

    //printf("%d",INF);
    while(scanf("%d",&n),n)
    {
        scanf("%d",&m);
        init();

        //printf("%d %d %d %d",dis[1][2],w[3],d[3],mode[3]);
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&ds);
            dis[a][b]=dis[b][a]=ds;
        }
        dp();
        dfs(1);
        printf("%d\n",w[1]);
    }
    return 0;
}
/*
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
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值