思路

  • 多起点最短路
  • 好像对于多起点的最短路,都是反着搜索。即从终点向起点搜索,这样搜索一次就可以了
  • 这题的坑点:坐标反着给
  • 注意是同时到达大本营的队伍成绩不算,不要看到火拼理解成在路上相遇的队伍(-_-)
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int N = 1e3 + 10, M = N * 2;
const int INF = 0x3f3f3f3f3f3f3f3f;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
int n, m, edx, edy;
int g[N][N], st[N][N], dist[N][N];
struct node
{
    int x, y;
};
void bfs(int x, int y)
{
    queue<node> q;
    q.push({x, y});
    dist[x][y] = 0;
    while(q.size())
    {
        node t = q.front();
        q.pop();
        int xx = t.x;
        int yy = t.y;
        //cout << xx << ' ' << yy << endl;
        for(int i = 0; i < 4; i ++)
        {
            int nex = xx + dx[i], ney = yy + dy[i];
            if(nex < 1 || nex > n || ney < 1 || ney > m) continue;
            if(st[nex][ney] || g[nex][ney] == 0) continue;
            st[nex][ney] = 1;
            dist[nex][ney] = dist[xx][yy] + 1;
            q.push({nex, ney});
        }
    }
}
signed main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= m; j ++)
        {
            cin >> g[i][j];
            if(g[i][j] == 2)
            {
                edx = i, edy = j;
            }
        }
    }
    memset(st, 0, sizeof st);
    memset(dist, -1, sizeof dist);
    bfs(edx, edy);
    int t;
    cin >> t;
    map<int, int> mp;
    vector<node> res;
    for(int i = 1; i <= t; i ++)
    {
        int x, y;
        cin >> y >> x;
        mp[dist[x][y]] ++;
        res.push_back({x, y});
    }
    int min_d = INF, id;
    for(int i = 0; i < t ; i ++)
    {
        int x = res[i].x, y = res[i].y;
        if(dist[x][y] == -1 || mp[dist[x][y]] > 1) continue;
        if(dist[x][y] < min_d)
        {
            min_d = dist[x][y];
            id = i + 1;
        }
    }
    if(min_d == INF)
    {
        cout << "No winner.";
    }
    else cout << id << ' ' << min_d << endl;
    return 0;
}