CCF-CSP 201403-4 无线网络

    xiaoxiao2021-03-25  54

    问题描述

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

    最短路径的问题的衍生。。。 先回忆下SPFA,我们在一般的SPFA中,可以只用一个一维数组保存当前得到的最小距离, 讲真也只需要一个一维的~~回到我们的问题上,可以想到应该是要把N+M个放到一起来做SPFA, 然而这里有个限制是那M个点最多只能取k个。 解决的办法是将一个点V在捆绑一个属性k,意思是找到点V的时候,经过几个M中的点。具体实现就是,SPFA在做入队操作时,本来是判断如果V不在队列中才将其加入队列,而现在是,只要没有相同k值的V在队列,就将这个(V,k)加入队列~ #include <iostream> #include <algorithm> #include <vector> #include <memory.h> #include <queue> #include <fstream> using namespace std; typedef long long LL; class Point { public: int x; int y; Point(int x = 0, int y = 0) :x(x), y(y){}; }; class Dist { public: int i; int k; Dist(int i = 0, int k = 0) :i(i), k(k){}; }; const int inf = 0x3f3f3f3f; const int maxn = 205; bool adj[maxn][maxn]; int ds[maxn][maxn]; bool vis[maxn][maxn]; int n, m, k, r; void spfa() { queue<Dist> q; q.push(Dist(0, 0)); vis[0][0] = true; ds[0][0] = 0; int tmpk = 0; Dist d; while (!q.empty()) { d = q.front(); q.pop(); vis[d.i][d.k] = false; for (int j = 0; j < n + m; j++) { tmpk = d.k; if (adj[d.i][j]) { if (j >= n) ++tmpk; if (tmpk <= k && ds[j][tmpk] > ds[d.i][d.k] + 1) { ds[j][tmpk] = ds[d.i][d.k] + 1; if (!vis[j][tmpk]) { q.push(Dist(j, tmpk)); vis[j][tmpk] = true; } } } } } } int main() { //ifstream cin("a.txt"); memset(adj, false, sizeof(adj)); memset(vis, false, sizeof(vis)); memset(ds, inf, sizeof(ds)); cin >> n >> m >> k >> r; vector<Point> pts; int x, y; for (int i = 0; i < n + m; i++) { cin >> x >> y; pts.push_back(Point(x, y)); } LL a, b; for (int i = 0; i < pts.size(); i++) { for (int j = 0; j < pts.size(); j++) { a = pts[i].x - pts[j].x; b = pts[i].y - pts[j].y; if ((a * a + b * b <= (LL)r * r)) adj[i][j] = true; } } spfa(); int ans = inf; for (int i = 0; i <= k; i++) ans = min(ans, ds[1][i]); cout << ans - 1 << endl; //cin.close(); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-37789.html

    最新回复(0)