版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/richenyunqi/article/details/87906639
欢迎访问我的CCF认证考试题解目录哦 https://blog.csdn.net/richenyunqi/article/details/83385502
题目描述
算法设计
将所有的路由器存储到一个vector
变量中。将每一个路由器看作是一个结点,结点编号为路由器在vector
中的下标,如果两个无线路由器只要距离不超过r
,就认为这两个路由器之间存在一条边,则整个问题就变成了求解0号结点到1号结点之间的最短路径。
由于最短路径的度量是最少经过的中转路由器的个数,所以可以把整个图看成是无权图,可以利用BFS算法求解,只不过在算法中需要考虑一下增设的路由器不能超过k
这个条件即可。具体实现可见代码。
注意点
由于涉及到平方运算,坐标以及r
最好都用long long
类型来存储。
C++代码
#include<bits/stdc++.h>
using namespace std;
struct Router{//路由器
long long x,y;//坐标
int cost=0,addNum=0;//经过的路由器个数、增设的路由器个数
bool add;//是否是增设的路由器
Router(long long xx,long long yy,bool a=false):x(xx),y(yy),add(a) {}
};
int n,m,k,r;
vector<Router>routers;//存储路由器
inline bool canReach(int i,int j){//计算两个路由器之间的距离是否超过r
return (routers[i].x-routers[j].x)*(routers[i].x-routers[j].x)+
(routers[i].y-routers[j].y)*(routers[i].y-routers[j].y)<=(long long)r*r;
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&r);
long long a,b;
while(n--){
scanf("%lld%lld",&a,&b);
routers.push_back(Router(a,b));
}
while(m--){
scanf("%lld%lld",&a,&b);
routers.push_back(Router(a,b,true));
}
vector<bool>inQueue(routers.size(),false);//标志一个路由器是否已经入过队
queue<int>q;
q.push(0);
inQueue[0]=true;
while(!q.empty()){
int t=q.front();
q.pop();
if(t==1)//到达1号结点,跳出循环
break;
for(int i=0;i<routers.size();++i)//遍历所有路由器
if(!inQueue[i]&&canReach(t,i)){//没有入过队且从t号路由器可以到达该路由器
if(routers[i].add&&routers[t].addNum+1>k)//如果该路由器是增设路由器且增设的路由器超过了k
continue;//不进行任何操作
routers[i].cost=routers[t].cost+1;//经过的路由器个数+1
routers[i].addNum=routers[t].addNum+(routers[i].add?1:0);//更新经过的增设路由器个数
inQueue[i]=true;
q.push(i);//入队
}
}
printf("%d",routers[1].cost-1);//输出
return 0;
}