Skip to content

试题编号: 201403-4

试题名称: 无线网络

时间限制: 1.0s

内存限制: 256.0MB

问题描述

原题链接: http://118.190.20.162/view.page?gpid=T7

​ 目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。   除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。   你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是多少?

输入格式

​ 第一行包含四个正整数 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100, 1 ≤ r ≤ 108)。   接下来 n 行,每行包含两个整数 xi 和 yi,表示一个已经放置好的无线 路由器在 (xi, yi) 点处。输入数据保证第 1 和第 2 个路由器在仅有这 n 个路由器的情况下已经可以互相连接(经过一系列的中转路由器)。   接下来 m 行,每行包含两个整数 xi 和 yi,表示 (xi, yi) 点处可以增设 一个路由器。   输入中所有的坐标的绝对值不超过 108,保证输入中的坐标各不相同。

输出格式

输出只有一个数,即在指定的位置中增设 k 个路由器后,从第 1 个路 由器到第 2 个路由器最少经过的中转路由器的个数。

样例输入

5 3 1 3
0 0
5 5
0 3
0 5
3 5
3 3
4 4
3 0

样例输出

2

思路

这道题目的基础是通过节点之间的距离判断节点之间是否连通,求出两个节点之间所需经过的最小中转次数。

可以被看作是是图论当中的求两节点之间最短路径的问题,等同于在每对直接连通的节点之间的路径长度为1的情况下(这样求出最短路径就等同于求出最小中转次数),求出两节点之间最短路径的问题。

用结构体定义每个节点,结构体之中设置一个k值来代表当遍历到当前节点时所选的额外节点的数目,通过这个数目的大小来判断下一步应该在什么范围的节点内遍历。

AC代码

#pragma GCC optimize(3, "Ofast", "inline")
#include <bits/stdc++.h>
#define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define rep(z, x, y) for(int z=x;z<=y;++z)
#define repd(z, x, y) for(int z=x;z>=y;--z)
#define ft first
#define sd second
#define pb push_back
const int maxn = 205;
const int mod = 998244353;
long long n, m, k, r, max1=-1;
bool vis[maxn];
using namespace std;

struct node {
    long long x, y, k;
    int step;
    node () { step = k = 0; }
    node (int x1, int y1, int s1, int k1) {x=x1;y=y1;step=s1;k=k1;}
} mmp[maxn];



int bfs(int beg, int ed){
    queue<node> Q;
    Q.push(node(mmp[beg].x, mmp[beg].y, 0, 0));
    vis[beg] = true;
    while (!Q.empty()) 
    {
        node s = Q.front();Q.pop();
        if (s.x == mmp[ed].x && s.y == mmp[ed].y) return s.step - 1;//求出中转个数 
        if (s.k == k) max1=n; // 当前k值一旦到达k时只能在n里面走,不能用mmp[n]之外的节点了 
        else max1=n+m;
        for (int i=1;i<= max1;++i) 
        {
            if (vis[i]) continue;
            if ((mmp[i].x - s.x)*(mmp[i].x - s.x) + (mmp[i].y - s.y)*(mmp[i].y - s.y) > r*r) continue;//距离不够就不走 
            vis[i] = true;
            int kk;
            if(i>n)kk=s.k+1;
            else kk=s.k;//根据当前节点的类型决定是否加k值
            Q.push(node(mmp[i].x, mmp[i].y, s.step + 1, kk));
        }
    }
}
int main()
{
    cin >> n >> m >> k >> r;
    rep(i,1,n+m)
        cin >> mmp[i].x >> mmp[i].y;
    cout << bfs(1, 2);//输入结果 
    return 0;
}