CCF CSP 201403-4 无线网络

CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址

CCF CSP 201403-4 无线网络

问题描述

  目前在一个很大的平面房间里有 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

解析

路由器构成了一个图,如果两个路由器的距离小于r则存在边。
求解的是最短路径。图所有边的权重均为1,因此可以用广度优先搜索解决。
搜索的时候需要记录路径上所经过的增设路由器的个数,并确保不会超过k。
使用广度优先搜索的层次遍历,可以方便地得到第1个路由器与第2个路由器之间的距离。

代码

C++

#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#define MAXN 210
using namespace std;

int N, M, K, R;
bool graph[MAXN][MAXN];
int pos[MAXN][2];

bool inRange(int a, int b, int R) {
    return sqrt(pow(pos[a][0]-pos[b][0],2)+pow(pos[a][1]-pos[b][1],2))<=R;
}

int bfs(int s, int t) {
    vector<bool> visited(M+N);
    queue<pair<int,int> > q;
    q.push(make_pair(s,0));
    int len = 1, newLen, level = 1;
    while(len>0) {
        newLen = 0;
        for(int l=0; l<len; l++) {
            pair<int,int> f = q.front();
            if(f.first == t) return level-2;
            q.pop();
            for(int i=0; i<N; i++) {
                if(graph[f.first][i] && !visited[i]) {
                    q.push(make_pair(i,f.second));
                    visited[i] = true;
                    newLen++;
                }
            }
            for(int i=N; i<N+M; i++) {
                if(graph[f.first][i] && !visited[i] && f.second<K) {
                    q.push(make_pair(i,f.second+1));
                    visited[i] = true;
                    newLen++;
                }
            }
        }
        len = newLen;
        level++;
    }
    return -1;
}

int main() {
    scanf("%d%d%d%d", &N, &M, &K, &R);
    for(int i=0; i<N+M; i++) {
        scanf("%d%d", &pos[i][0], &pos[i][1]);
    }
    for(int i=0; i<N+M; i++) {
        for(int j=i+1; j<N+M; j++) {
            graph[i][j] = graph[j][i] = inRange(i, j, R);
        }
    }
    printf("%d", bfs(0, 1));
}

 

posted on 2017-10-16 16:44  meelo  阅读(1501)  评论(2编辑  收藏  举报