PAT Advanced—1003 Emergency (25分)

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.
Input Specification:
Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C​1​​ and C​2​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c​1​​, c​2​​and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1​​ to C​2​​.
Output Specification:
For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:
5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1
Sample Output:
2 4

思路:
  题目要求出最短路径的条路,并且要找到最短路径中的最大救援队数,典型的路径搜索问题,可以使用DFS来全局搜索,也可以利用分支限界的思想来提高效率,只需要一个判读语句即可。

注意:

  1. DFS可能需要传比较多的参数,可以将这些参数定义为全局变量即可
  2. 可以利用分支限界法的思想,对于不满足最小的路径不再往下搜索,提升效率

代码:(C++)

#include<iostream>
#include<cmath>
#include<cstring>

#define MAX_VALUE 501
#define MAX_INT 0x3f3f3f3f

using namespace std;

int n, m, cur, obj;
int map[MAX_VALUE][MAX_VALUE];  //保存地图,线路
int rescue[MAX_VALUE];  //保存各城市救援人数
int min_dis = MAX_INT;  //保存最小距离
int max_res = 0;  //保存最大助手
int visited[MAX_VALUE];  //保存是否访问过该城市
int cur_way = 0; //当前路线距离
int cur_res = 0; //当前最大助手
int num = 0;  //记录有多少最短路径

void DFS(int c)
{
    if(c == obj)
    {
        if(cur_way < min_dis)
        {
            num = 1; //找到更短了的,重置为1
            max_res = cur_res;
            min_dis = cur_way;
        }
        else if(cur_way == min_dis)
        {
            num++;  //找到一条一样长的路径,条数+1
            max_res = max(max_res, cur_res);
        }
    }
    else
    {
        visited[c] = 1;  //说明此城市被访问了
        for(int i=0; i<n; i++)
        {
            if(map[c][i] != -1 && visited[i] != 1)
            {
                cur_res += rescue[i];
                cur_way += map[c][i];
                if(cur_way <= min_dis)  //分支限界一下,提高效率
                    DFS(i);  //深度遍历
                cur_res -= rescue[i];  //回溯
                cur_way -= map[c][i];
            }
        }
        visited[c] = 0;  //该城市的所有路径访问完了,回溯之后,设置为可以访问了
    }
}

int main()
{

    cin>>n>>m>>cur>>obj;
    memset(map,-1,sizeof(map));
    memset(visited, 0, sizeof(visited));
    for(int i=0; i<n; i++)
        cin>>rescue[i];
    for(int i=0; i<m; i++)
    {
        int x,y,dis;
        cin>>x>>y>>dis;
        map[x][y] = dis;
        map[y][x] = dis;  //无向图
    }
    cur_res += rescue[cur];  //带上自己城市的帮手
    DFS(cur);
    
    cout<<num<<" "<<max_res;
    return 0;
}

效率分析:

  1. 未使用分支限界思想
    在这里插入图片描述

  2. 使用分支限界思想
    在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值