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): 8342    Accepted Submission(s): 3081

题目链接
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

题目意思:

之前误解题目意思了,以为是要求点1到2的最短路的条数,然而这个题目还巧了,按照这个错误的理解一写算法,输入题目中的测试数据,答案还刚好是2和4,阿西吧,这也太巧了吧。后果惨痛的代价就是做题做了好久好久,都是错的,浪费好多时间。最后问了学长才明白了题目的真实意思。感觉自己好蠢。

题目要走的道路是 1...A->B...2。首先如果A到B有路,如果B到2的最短路比A到2的任何道路都短,则可以从A走到B,意思就是只要A要B有路,且B到2的最短路比A到2的最短路段,则就可以从A走到B。求从点1走到点2的道路条数。

解题思路:

先求出2到其他点的最短路。然后记性记忆化搜索,设置road[i]存放点i到2的道路条数,初始化为0.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#define INF 0x3f3f3f3f

using namespace std;

int dist[1010];
int Map[1010][1010];
int vis[1010];
int road[1010];
int N,M;                ///点的个数和道路条数
void Djistra(int start) ///先求点2到其他点的最短路
{
    int i,j,u,mindis;
    for(i = 1; i <= N; i++)
    {
        vis[i] = 0;     ///代表点i没有找到最短路径
        dist[i] = Map[start][i];  ///最短路径进行初始化
    }
    vis[start] = 1;
    for(i = 1; i <= N; i++)
    {
        u = 0;
        mindis = INF;
        for(j = 1; j <= N; j++)
        {
            if(vis[j]==0 && dist[j]<mindis)
            {
                mindis = dist[j];
                u = j;
            }
        }
        if(u == 0)  ///代表所有点都已经找到最短路,直接结束,减少时间复杂度
            break;
        vis[u] = 1;
        for(j = 1; j <= N; j++)
        {
            if(vis[j]==0)
            {
                if(Map[u][j]<INF && dist[u]+Map[u][j]<dist[j])
                    dist[j] = dist[u] + Map[u][j];
            }
        }
    }
}
int dfs(int node)
{
    if(road[node]>0) return road[node];  ///如果road[node]已经有值,代表之前已经求过了,不用再递归去求解了,否则一直递归下去会超时
    if(node == 2) return 1;  ///如果节点的值为2,则说明已经到达终点了
    int sum = 0;             ///sum用于计算当前节点到2的道路条数
    for(int i = 1; i <= N; i++)
    {
        if(Map[node][i]<INF && dist[i]<dist[node])  ///能从node走到i,且i到2的最短路比node到2的最短路短
        {
            sum += dfs(i);   ///node到2的道路条数要加上i到2的道路条数
        }
        road[node] = sum;  ///当前node到2的道路条数
    }
    return sum;  ///返回node到2的道路总条数
}
int main()
{
    int a,b,dis;
    while(scanf("%d",&N))  ///输入点数
    {
        if(N == 0)
            break;
        scanf("%d",&M);  ///路的条数
        for(int i = 1; i <= N; i++)  ///图的初始化工作
        {
            road[i] = 0;
            for(int j = 1; j <= N; j++)
            {
                if(i == j)
                    Map[i][j] = 0;
                else
                    Map[i][j] = INF;
            }
        }
        for(int i = 1; i <= M; i++)
        {
            scanf("%d%d%d",&a,&b,&dis);
            Map[a][b] = Map[b][a] = dis;  ///题目中说了,对于一条路,它可以从任何方向走,则应该是无向图
        }
        Djistra(2);  ///用狄克斯特拉求2到其他点的最短路
        int ans = dfs(1);   ///用递归求1到2的道路条数
        printf("%d\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值