CCF-CSP 201403-4 无线网络

来源:互联网 发布:淘宝食品店名 编辑:程序博客网 时间:2024/05/06 20:21

问题描述

  目前在一个很大的平面房间里有 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;}
0 0
原创粉丝点击