• 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++)
    		{
    			if(j != i)
    			{
    				road[i][j] = INF;
    				road[j][i] = INF;
    			}
    			//当i==j的时候,一定要赋值为0,否则当起点src和终点des相同的时候,test case是过不了的。
    			else
    				road[i][j] = 0;
    		}
    	}
    }
    
    //单源最短路径算法。
    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;
    
    	dfs(n,src,des,0,team_num[src]);
    
    	cout<<path_num<<" "<<g_max_team_num<<endl;
    	return 0;
    }
    

      

  • 相关阅读:
    Leetcode: 1425
    Leetcode: 1508 Range Sum of Sorted Subarray Sums
    Leetcode: 1353. Maximum Number of Events That Can Be Attended
    Leetcode: 1424. Diagonal Traverse II
    Leetcode: 825. Friends Of Appropriate Ages
    非递归实现二叉树的前序,中序,后序遍历
    TCP协议详解
    Linux常见命令
    C++基础笔记
    指针和引用的区别
  • 原文地址:https://www.cnblogs.com/yanhaiming/p/2797037.html
Copyright © 2020-2023  润新知