问题描述
目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。
除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。 你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是多少?
输入格式
第一行包含四个正整数 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100, 1 ≤ r ≤ 10
8)。
接下来 n 行,每行包含两个整数 x i 和 y i,表示一个已经放置好的无线 路由器在 (x i, y i) 点处。输入数据保证第 1 和第 2 个路由器在仅有这 n 个路由器的情况下已经可以互相连接(经过一系列的中转路由器)。 接下来 m 行,每行包含两个整数 x i 和 y i,表示 (x i, y i) 点处可以增设 一个路由器。 输入中所有的坐标的绝对值不超过 10 8,保证输入中的坐标各不相同。
输出格式
输出只有一个数,即在指定的位置中增设 k 个路由器后,从第 1 个路 由器到第 2 个路由器最少经过的中转路由器的个数。
样例输入
5 3 1 3
0 0 5 5 0 3 0 5 3 5 3 3 4 4 3 0
样例输出
2
|
<textarea readonly="readonly" name="code" class="c++">
#include <iostream>
#include <queue>
#include <cstring>
#include <climits>
using namespace std;
int M[200+10][200+10],d[200+10];
int m,n,k,stat;
long long r;
int vis[200+10];
typedef struct Point
{
long long x;
long long y;
};
Point G[200+10];
int com(long long x1,long long y1,long long x2,long long y2)
{
if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)>r*r||((x1==x2)&&(y1==y2))) return 0;
else return 1;
}
void bfs(long s)
{
queue<long> q;
int stat;
q.push(s);
for(int i=0;i<n+m;i++) d[i]=INT_MAX;
memset(vis,0,sizeof(vis));
d[s]=0;
int u;
while(!q.empty())
{
u=q.front();
q.pop();
for(int v=0;v<n+m;v++)
{
if(M[u][v]==0) continue;
if(d[v]!=INT_MAX) continue;
if(v>=n)
if(vis[v]<k)
{
stat++;
vis[u]=vis[u]+vis[v];
}
else continue;
d[v]=d[u]+1;
q.push(v);
}
}
cout<<d[1]-1<<endl;
}
int main()
{
cin>>n>>m>>k>>r;
for(int i=0;i<n+m;i++)
{
cin>>G[i].x>>G[i].y;
}
for(int i=0;i<n+m;i++)
for(int j=0;j<n+m;j++)
{
if(com(G[i].x,G[i].y,G[j].x,G[j].y))
M[i][j]=M[j][i]=1;
else
M[i][j]=0;
}
bfs(0);
return 0;
}
</textarea>
对于上面道题,我使用的方法是广度优先搜索算法,当然在利用刚度优先搜索算法解题的时候,要注意设计一个用于记录的数组来记录当前访问的点所经过的中间路由器的数目。