zoukankan      html  css  js  c++  java
  • hdu 1142 A Walk Through the Forest(spfa+记忆化搜索)

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

    题意:有n个点,m条边带权的无向图,点1为起点,点2为终点。求点1到点2有几条路,路的限制是每过一个点,都要后点到2的距离小于前点的距离。

    思路:先用spfa/dijkstra算一遍每个点到2的最短距离。再搜索一下符合题意的路,普通的dfs是肯定超时的。这里用到记忆化搜索,用到动态规划的思想,dp[i]记录点i到2有几条符合题意的路。当搜索到已经搜索过的点,直接加就可以了,不用再搜。比如:3到2有2条路(即dp[3]=2),搜索4时,4和3连通,再搜索3时,dp[4]+=dp[3]。就不用重复操作。

    记忆化搜索代码:

    int dfs(int k){//返回几条符合的路 
        if(dp[k] > 0)    return dp[k];//dp初始值为0,已经搜索过,直接返回dp值 
        if(k == 2)    return 1;//搜索终点,搜索到2,说明这是条符合的路, 
        for(int i = head[k]; i != -1 ;i = edge[i].next){// 查找连通的点 
            int v = edge[i].to;
            if(d[k] > d[v])//符合要求,继续搜索直到搜索到2或已经搜索过 
                dp[k] += dfs(v);    
        }
        //cout<<k<<" "<<dp[k]<<endl;
        return dp[k];
    }

    完整代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+10;
    struct node{
        int from,to,w,next;
    }edge[maxn*maxn];
    int d[maxn],head[maxn*maxn],visit[maxn],dp[maxn];
    int n,m,cnt;
    
    void init(){//初始化 
        memset(head,-1,sizeof(head));
        memset(d,0x3f,sizeof(d));
        memset(visit,0,sizeof(visit));
        memset(dp,0,sizeof(dp));
        cnt=0;
    }
    
    void add(int u,int v,int w){//前向星连边 
        edge[cnt].from=u;
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    int dfs(int k){//返回几条符合的路 
        if(dp[k] > 0)    return dp[k];//dp初始值为0,已经搜索过,直接返回dp值 
        if(k == 2)    return 1;//搜索终点,搜索到2,说明这是条符合的路, 
        for(int i = head[k]; i != -1 ;i = edge[i].next){// 查找连通的点 
            int v = edge[i].to;
            if(d[k] > d[v])//符合要求,继续搜索直到搜索到2或已经搜索过 
                dp[k] += dfs(v);    
        }
        //cout<<k<<" "<<dp[k]<<endl;
        return dp[k];
    }
    
    void spfa(){//spfa求到2的最短路 
        queue<int> q;
        q.push(2);
        visit[2]=1;
        d[2]=0;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            visit[u]=0;
            for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].to;
                int w=edge[i].w;
                if(d[v]>d[u]+w){
                    d[v]=d[u]+w;
                    if(!visit[v]){
                        visit[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main(){
        while(scanf("%d",&n)!=EOF&&n){
            init();
            scanf("%d",&m);
            int u,v,w;
            for(int i=0;i<m;i++){
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);//无向图 
                add(v,u,w);
            }
            spfa();
            printf("%d
    ",dfs(1));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    谈谈Oracle基本操作(下)
    谈谈Oracle基本操作(上)
    java理论之java多线程与网络编程
    java理论之java--GUI(图形用户管理)与 IO/流
    java理论之java数组和集合
    存图片的
    .html()渲染后的内容还是带标签的字符串的问题
    Vuejs报错error: Unexpected console statement (no-console) at src... 解决办法
    常用正则表达式
    移动WEB---01.关于屏幕像素
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10294721.html
Copyright © 2011-2022 走看看