zoukankan      html  css  js  c++  java
  • CCF201403 无线网络【限制型最短路】

    问题描述
      目前在一个很大的平面房间里有 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.首先建图,对于任意两个距离小于 r 的点连无向边。边权设为 1。当找到1与2的最短路,那么中转的点的数量就是dis[2] - 1。
    2.因为是在m个点选择k个点增设。那么每次从队列中选择一个点进行松弛的时候,要判断 to 的编号是否大于 n ,以及目前已经选择了多少个点,不得超过k。
    3.用vis[][]二维数组来记录状态,表示 i 点在已经选择增设了 k 个点的情况下 是否存在于队列中。
    4.需要注意在比较距离是否小于r时,数据会爆int。要先转化成ll型或者直接开ll型的数组。
    代码如下:
      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<queue>
      4 #define mem(a, b) memset(a, b, sizeof(a))
      5 typedef long long ll;
      6 using namespace std;
      7 const int MAXN = 210;
      8 const int inf = 0x3f3f3f3f;
      9 
     10 int n, m, k;
     11 ll r; //n + m个点 其中 m 个点是可选择添入的 最后可增设其中 k 个点。 
     12 ll x[MAXN], y[MAXN];
     13 int head[MAXN], cnt, vis[MAXN][110], dis[MAXN];
     14 
     15 struct Edge
     16 {
     17     int to, next, w;
     18 }edge[MAXN * (MAXN - 1)];
     19 
     20 struct Node
     21 {
     22     int pot, num;
     23 }node;
     24 
     25 void add(int a, int b, int c)
     26 {
     27     cnt ++;
     28     edge[cnt].to = b;
     29     edge[cnt].w = c;
     30     edge[cnt].next = head[a];
     31     head[a] = cnt;
     32 }
     33 
     34 void spfa()
     35 {
     36     queue<Node> Q;
     37     node.pot = 1, node.num = 0;
     38     dis[1] = 0;
     39     vis[1][0] = 1;
     40     Q.push(node);
     41     while(!Q.empty())
     42     {
     43         Node a = Q.front();
     44         Q.pop();
     45         vis[a.pot][a.num] = 0;
     46         for(int i = head[a.pot]; i != -1; i = edge[i].next)
     47         {
     48             int to = edge[i].to;
     49             int p = a.num;
     50             if(to > n)
     51                 p ++;
     52             if(dis[to] > dis[a.pot] + edge[i].w && p <= k)
     53             {
     54                 dis[to] = dis[a.pot] + edge[i].w;
     55                 if(!vis[to][p])
     56                 {
     57                     vis[to][p] = 1;
     58                     node.pot = to, node.num = p;
     59                     Q.push(node);
     60                 }
     61             }
     62         }
     63     }
     64 }
     65 
     66 int main()
     67 {
     68     mem(head, -1), cnt = 0;
     69     mem(vis, 0), mem(dis, inf);
     70     scanf("%d%d%d%lld", &n, &m, &k, &r);
     71     for(int i = 1; i <= n + m; i ++)
     72         scanf("%lld%lld", &x[i], &y[i]);
     73     for(int i = 1; i < n + m; i ++)
     74     {
     75         for(int j = i + 1; j <= n + m; j ++)
     76         {
     77             if((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) <= r * r)
     78             {
     79                 add(i, j, 1);
     80                 add(j, i, 1);
     81             }
     82         }
     83     }
     84     spfa();
     85     printf("%d
    ", dis[2] - 1);
     86     return 0;
     87 }
     88 
     89 /*
     90 测试数据:
     91 5 3 1 3
     92 0 0
     93 5 5
     94 0 3
     95 0 5
     96 3 5
     97 3 3
     98 4 4
     99 3 0
    100 2
    101 
    102 10 1 1 2
    103 0 0
    104 3 1
    105 -2 0
    106 -2 2
    107 -2 4
    108 -2 6
    109 0 6
    110 2 6
    111 2 4
    112 2 2
    113 2 0
    114 1
    115 
    116 10 1 1 2
    117 0 0
    118 3 1
    119 -2 0
    120 -2 2
    121 -2 4
    122 -2 6
    123 0 6
    124 2 6
    125 2 4
    126 2 2
    127 3 0
    128 8
    129 
    130 6 3 2 50000000
    131 0 0
    132 50000000 100000000
    133 100000000 100000000
    134 100000000 0
    135 100000000 50000000
    136 50000000 0
    137 -100000000 50000000
    138 0 50000000
    139 0 100000000
    140 2
    141 */
    View Code
  • 相关阅读:
    解决 git 同步时 Everything up-to-date
    vs2019 git Authentication failed for xxx
    vs2015发布项目到虚拟主机组策略阻止csc.exe程序问题
    vs2017 使用 reportviewer
    var,dynamic的用法
    水晶报表报无法在资源中找到报表,请重新创建项目 错误
    css隐藏元素的方法
    css-浮动与清除浮动的原理详解(清除浮动的原理你知道吗)
    正则并不适合严格查找子串
    浏览器加载、渲染过程总结
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/11863201.html
Copyright © 2011-2022 走看看