7-4 Ambulance Dispatch (30分)

Given the map of a city, with all the ambulance dispatch centers (救护车派遣中心) and all the pick-up spots marked. You are supposed to write a program to process the emergency calls. It is assumed that the callers are waiting at some pick-up spot. You must inform the nearest (that is, to take the minimum time to reach the spot) dispatch center if that center has at least one ambulance available. Note: a center without any ambulance must not be considered.

In case your options are not unique, inform the one with the largest number of ambulances available. If there is still a tie, choose the one that can pass the least number of streets to reach the spot, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive integers N​s​​ (≤10​3​​) and N​a​​ (≤10), which are the total number of pick-up spots and the number of ambulance dispatch centers, respectively. Hence the pick-up spots are numbered from 1 to N​s​​, and the ambulance dispatch centers are numbered from A−1 to A−N​a​​.

The next line gives N​a​​ non-negative integers, where the i-th integer is the number of available ambulances at the i-th center. All the integers are no larger than 100.

In the next line a positive number M (≤10​4​​) is given as the number of streets connecting the spots and the centers. Then M lines follow, each describes a street by giving the indices of the spots or centers at the two ends, followed by the time taken to pass this street, which is a positive integer no larger than 100.

Finally the number of emergency calls, K, is given as a positive integer no larger than 10​3​​, followed by K indices of pick-up spots.

All the inputs in a line are separated by a space.

Output Specification:

For each of the K calls, first print in a line the path from the center that must send an ambulance to the calling spot. All the nodes must be separated by exactly one space and there must be no extra space at the beginning or the end of the line. Then print the minimum time taken to reach the spot in the next line. It is assumed that the center will send an ambulance after each call. If no ambulance is available, just print All Busy in a line. It is guaranteed that all the spots are connected to all the centers.

Sample Input:

7 3
3 2 2
16
A-1 2 4
A-1 3 2
3 A-2 1
4 A-3 1
A-1 4 3
6 7 1
1 7 3
1 3 3
3 4 1
6 A-3 5
6 5 2
5 7 1
A-2 7 5
A-2 1 1
3 5 1
5 A-3 2
8
6 7 5 4 6 4 3 2

Sample Output:

A-3 5 6
4
A-2 3 5 7
3
A-3 5
2
A-2 3 4
2
A-1 3 5 6
5
A-1 4
3
A-1 3
2
All Busy
  • 为了这题:冲了50块,投资教育了…

  • 考试遇到这题,直接…原地去世…

  • 分析:地图上有两种点:求助点 和 医院点,
    最多1000次求助,每次求助:从求助点找:

  1. 到求助点路径最短(即时间最短)的医院
  2. 若相同则,车最多的医院
  3. 若还同则,路径上经过街道(边)最少的医院

【注意】最后一个测试点,可能解不唯一,要选编号大的那个结果…我猜的

  • 思路 1:直接DFS:每次从求助点出发,DFS全图找符合条件的医院,在剪枝,反正我没剪成功
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1020, INF = 0x3fffffff;
int cars[20], ns, na;
struct node
{
   
    int nex, dis;
};
vector<node> G[maxn];

bool vis[maxn]; //控制单向前进,同时每走一步,释放前面节点控制权
vector<int> tmp, ans;
void DFS(int id, int len, int & min_cost, int & max_cars, int & min_edge)
{
   
    if(len > min_cost) return;
    else if(len == min_cost)
    {
   
        if(id <= ns || cars[id-ns] <= 0)
        {
   
            return;
        }else if(cars[id - ns] < max_cars)
        {
   
            return;
        }else if(tmp.size() - 1 >= min_edge)
        {
   
            return;
        }
    }
    tmp.push_back(id);
    if(id > ns && cars[id - ns] > 0)  //走到医院了
    {
   
        if(len < min_cost)
        {
   
            min_cost = len;
            max_cars = cars[id-ns];
            min_edge = tmp.size()-1;
            ans = tmp;
        }else if(len == min_cost)
        {
   
            if(cars[id-ns] > max_cars)
            {
   
                max_cars = cars[id-ns];
                min_edge = tmp.size()-1;
                ans = tmp;
            }else if(cars[id-ns] == max_cars && tmp.size()-1 <= min_edge)
            {
   
                min_edge = tmp.size()-1;
                ans = tmp;
            }
        }
        tmp.pop_back();
        return;
    }
    vis[id] = true;
    for(int i = 0; i < G[id].size(); ++i)
    {
   
        int nex = G[id][i].nex;
        int dis = G[id][i].dis;
        if(vis[nex] == false)
        {
   
            DFS(nex, len + dis, min_cost, max_cars, min_edge);
        }
    }
    tmp.pop_back();
    vis[id] = false;
}


int Change(char s[]);
void Print(const vector<int> & v);
int main()
{
   
    scanf("%d %d", &ns, &na);
    for(int i = 1; i <= na; ++i) scanf("%d", &cars[i]);
    int m;
    scanf("%d", &m);
    for(int i = 0; i < m; ++i)
    {
   
        char v1[10], v2[10];
        int tcost;
        scanf("%s %s %d", v1, v2, &tcost);
        int id1 = Change(v1), id2 = Change(v2);
        G[id1].push_back(node{
   id2, tcost});
        G[id2].push_back(node{
   id1, tcost});
    }
    int nq;
    bool lock = false;
    scanf("%d", &nq);
    for(int i = 0; i < nq; ++i)
    {
   
        int pick_up, MIN_COST = INF, MAX_CARS = -1, MIN_EDGE = INF;
        scanf("%d", &pick_up);
        if(lock == false)
        {
   
            DFS(pick_up, 0, MIN_COST, MAX_CARS, MIN_EDGE);
        }
        if(ans.size() == 0)
        {
   
            printf("All Busy\n");
            lock = true;
        }else
        {
   
            Print(ans);
            printf("%d\n", MIN_COST);
            cars[ans[ans.size()-1]-ns]--;
        }
        ans.clear();
    }
    return 0;
}

/*---------------------------------------------------------*/

int Change(char s[])
{
   
    int ans;
    if(s[0] == 'A')
    {
   
        sscanf(s, "A-%d", &ans);
        ans += ns;
    }else
    {
   
        ans = atoi(s);
    }
    return ans;
}

void Print(const vector<int> & v)
{
   
    for(int i = v.size()-1; i >= 0; --i)
    {
   
        if(ans[i] > ns) printf("A-%d", ans[i]-ns);
        else printf("%d", ans[i]);
        if(i != 0) printf(" ");
        else printf("\n");
    }
}

  • 结果:
    在这里插入图片描述
  • 思路 2: 对每个求助点Dijkstra,再DFS找最优医院
    每次求助:
    step 1: 对求助点Dijkstra求出到所有点的最短距离
    step 2: 遍历所有有车的医院,每次先用DFS求出该医院到求助点的经过街道最少的路径,然后三重if_else看该医院能否优化全局最优解
    step 3: 判断并输出全局最优解
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1020, INF = 0x3fffffff;
int ns, na, cars[20], G[maxn][maxn], d[maxn];
bool vis[maxn];
struct node
{
   
    int id, d;
    bool operator < (const node & tmp) const {
    return d > tmp.d; }
};
vector<int> pre[maxn];
void Dijkstra(int start)
{
   
    fill(d, d + na + ns + 1, INF);
    memset(vis, false, sizeof(vis));    //和上面哪个快?
    d[start] = 0;
    priority_queue<node> pq;
    pq.push(node{
   start, 0});
    while(!pq.empty())
    {
   
        node now = pq.top();
        pq.pop();
        if(vis[now.id]) continue;
        vis[now.id] = true;
        for(int i = 1; i <= na + ns; ++i)
        {
   
            if(vis[i] == false && G[now.id][i] != 0)
            {
   
                if(now.d + G[now.id][i] < d[i])
                {
   
                    d[i] = now.d + G[now.id][i];
                    pre[i].clear();
                    pre[i].push_back(now.id);
                    pq.push(node{
   i, d[i]});
                }else if(now.d + G[now.id][i] == d[i])
                {
   
                    pre[i].push_back(now.id);
                    pq.push(node{
   i, d[i]});
                }
            }
        }
    }
}
vector<int> tmp, ans;
void DFS(int id, int s, int & min_edge)
{
   
    if(tmp.size() > min_edge) return;
    tmp.push_back(id);
    if(id == s)
    {
   
        if(tmp.size()-1 < min_edge)
        {
   
            min_edge = tmp.size()-1;
            ans = tmp;
        }
        tmp.pop_back();
        return;
    }
    for(int i = 0; i < pre[id].size(); ++i)
    {
   
        int nex = pre[id][i];
        DFS(nex, s, min_edge);
    }
    tmp.pop_back();
}

int Change(char s[]);
void Print(const vector<int> & v);
int main()
{
   
    scanf("%d %d", &ns, &na);
    for(int i = 1; i <= na; ++i)
    {
   
        scanf("%d", &cars[i]);
    }
    int m;
    scanf("%d", &m);
    for(int i = 0; i < m; ++i)
    {
   
        char tmp1[10], tmp2[10];
        int tmp_cost;
        scanf("%s %s %d", tmp1, tmp2, &tmp_cost
  • 13
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值