您的位置:首页 > 理论基础 > 计算机网络

CCF CSP 无线网络 BFS

2017-03-29 21:20 357 查看
问题描述

  目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。

  除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。

  你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是多少?

输入格式

  第一行包含四个正整数 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100,)。

  接下来 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、解题分析

要求找“最短”,每次都是从一个状态转移到另一个状态,可以使用广搜解决。需要确认BFS时各节点表示的状态是用哪几个参数表示。题目输入的坐标访问可以很大,所以需要离散化存储坐标,在vector中连续的存储输入的坐标,这样可以用数组的下标id去确定任意一个路由器。那么广搜树上每个节点所表示的状态就是由三个参数组成:id表示路由器的坐标,step表示到该状态时中转了多少个路由器,k_num表示到该状态时已经新设了多少个路由器。

2、坑点说明

只需要注意数据规模,1 ≤ r,x,y≤ 108,如果是int类型的数,因为int是32位的,所以最大可以表示到232,也就是4,294,967,296。对于表示108并没有问题,但是我的程序里需要比较两个路由器之间的距离需要对r、x、y做平方,那么就得用到最大可表示的long
long类型存储了。我开始就是这里给扣了20分。

还有一个需要吐槽的,这题的测试数据,似乎对k没有做任何要求,我看有的程序不对k做设置都行。。。

代码如下:

#include<iostream>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;
#define LL long long
#define INF 1<<31
int n,m,k;
LL r;
struct node{
LL x;
LL y;
}N;
struct info{
LL step;//经过了多少个路由器
LL k_num;//新设置了几个路由器
int id;//该节点的序号
}T;
queue<struct info> q;
vector<struct node> vec;
bool get[220];
bool Judge(LL x1,LL y1,LL x2,LL y2)
{
LL x = x1-x2;
LL y = y1-y2;
//	cout << "x1=" << x1<<" y1="<<y1<<" x2="<<x2<<" y2="<<y2<< " x="endl;
if( (x*x + y*y) <= r*r)
{
return true;
}else{
return false;
}
}
int BFS()
{
struct info new_T;
int id;
LL num=INF;//置为最大值
T.step=0;
T.k_num=0;
T.id=0;
q.push(T);
get[0]=true;
while(!q.empty())
{
new_T = q.front();
q.pop();
id = new_T.id;

if(Judge(vec[id].x,vec[id].y,vec[1].x,vec[1].y))
{
/*if(new_T.step<num)
{
num = new_T.step;
}*/
return new_T.step;
}
for(int i=0;i<vec.size();i++)
{
if(!get[i] && i!=id && Judge(vec[id].x,vec[id].y,vec[i].x,vec[i].y))
{

if(new_T.k_num==k && i>=n)//当前以及选中k个新设立的路由器,不能再加入新的路由器
{
continue;
}
get[i]=true;
T.step=new_T.step+1;
if(i>=n)//说明是新设的路由器
{
T.k_num=new_T.k_num+1;
}else{
T.k_num=new_T.k_num;
}
T.id=i;
q.push(T);
}
}
}
return num;
}
int main()
{
long long x,y;
cin >> n >> m >> k >> r;
for(int i=0;i<n+m;i++)
{
cin >> N.x >> N.y;
vec.push_back(N);
}
cout << BFS();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: