zoukankan      html  css  js  c++  java
  • PAT 1003 Emergency 深度优先搜索 (剪枝方案二,优化后)

    #include<iostream>
    #include<cstring>
    using namespace std;
    
    const int N = 1000;
    const int INF = 100000000;
    
    //图的邻接矩阵
    int road[N][N];
    
    //标记某一节点是否被访问过
    bool isVisited[N];
    
    //记录每一节点的权值
    int team_num[N];
    
    int dis[N];
    
    //最短路径的数目
    int path_num =0;
    
    //最大的医疗队的数目
    int g_max_team_num = 0;
    
    void initData()
    {
        int i,j;
        for(i=0; i<N; i++)
        {
            isVisited[i] = false;
            team_num[i] = 0;
            dis[i] = INF;//初始化为无穷大.
            for(j=0; j<N; j++)
            {
                road[i][j] = INF;
                road[j][i] = INF;
            }
        }
    }
    
    //单源最短路径算法。
    void Dijstra(int n,int src, int des)
    {
        int i,j;
        for(i=0; i<n; i++)
            dis[i] = road[src][i];
        isVisited[src] = true;
    
        for(i=0; i<n-1; i++)//最多循环n-1次就足够了,选n-1个最小值。
        {
            int minDis = INF;
            int cur = 0;
            for(j=0; j<n; j++)
                if(!isVisited[j] && dis[j]<minDis)
                {
                    minDis = dis[j];
                    cur = j;
                }
            if(minDis == INF) //已经完成了连通路径的遍历。
                return;
            //dis[cur]为dis数组中的最小值,访问节点cur.
            isVisited[cur] = true;
            //更新Dis数组的内容.
            for(j=0; j<n; j++)
                if(road[cur][j] <INF && dis[j] > dis[cur] + road[cur][j])
                    dis[j] = dis[cur] + road[cur][j];
        }
    }
    //深度搜索来得到最短路径的数目。
    void dfs(int n,int cId,int des,int curDis,int curTeamsNum)
    {
        isVisited[cId] = true;
        if(cId == des)
        {
            if(curDis == dis[des]) //找到一条最短路径
            {
                path_num++;//最短路径数目加1
                if(curTeamsNum > g_max_team_num)
                    g_max_team_num = curTeamsNum;
            }
            return;
        }
        if(curDis > dis[des]) //当前的路径长度已经超过最短路径,就没有必要继续搜索了。
            return;    
        //从城市cId开始搜索
        for(int i=0; i<n; i++)
        {
            /*
            if(!isVisited[i] && road[cId][i] < INF)//如果城市i没有被访问过,且cId到i连通。        
            {
                //isVisited[i] = true;
                dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]);
                isVisited[i] = false;
            }
            */
            //这样的剪枝比上一种更加强大。
            if(dis[cId] + road[cId][i] == dis[i])
                dfs(n,i,des,curDis+road[cId][i],curTeamsNum+team_num[i]);
        }
    }
    
    int main()
    {
        int i,j,n,m,c1,c2,L,src,des;
    
        initData();
    
        cin>>n>>m>>src>>des;
        for(i=0; i<n; i++)
            cin>>team_num[i];
        for(i=0; i<m; i++)
        {
            cin>>c1>>c2>>L;
            road[c1][c2] = L;
            road[c2][c1] = L;
        }
        
        Dijstra(n,src,des);
    
        //重置各city的被访问状态。
        for(i=0; i<n; i++)
            isVisited[i] = false;
    
        dis[src] = 0;
        dfs(n,src,des,0,team_num[src]);
    
        cout<<path_num<<" "<<g_max_team_num<<endl;
        return 0;
    }
  • 相关阅读:
    第五课 主引导程序的扩展 下
    C.Candy
    B.大钉骑马走江湖
    A喝酒(北京林业大学校赛)
    HDU 5666 Segment
    南京理工大学第八届校赛题目题解(部分)
    TCO 2016 Round 1B
    139. Word Break
    90. Subsets II
    78. Subsets
  • 原文地址:https://www.cnblogs.com/yanhaiming/p/2797064.html
Copyright © 2011-2022 走看看