【CCF-CSP】201403-4 无线网络 C++ BFS


一、题目

无线网络

原题目链接

二、解题

1.利用BFS求解

以下这段代码实现了一个广度优先搜索算法(bfs)来查找一个有权有向图中,从点0到点1的最短路径长度。这里的点编号从0开始,而点0是起点,点1是终点。对于一个由n个普通点和m个特殊点组成的有向图,其中k表示每个点最多可以经过的次数,r表示两个点之间的距离不能超过r,c[i]表示当前到点i的路径经过的普通点数,cnt_n表示当前路径经过的普通点数,cnt_t表示经过特殊点的次数。

算法流程如下:

  1. 首先定义一个队列,将起点(0, 0, 0)加入队列。
  2. 使用fill函数将c数组初始化,设置为k+1,表示尚未到任何一个点。
  3. 取出队首元素temp,分别取出其节点编号(index)、当前经过的普通点数(c1)、经过特殊点的次数(c2)。
  4. 如果当前节点为终点1,则返回经过特殊点的次数(c2-1)。
  5. 对于当前节点temp,遍历它所能到达的所有节点i。
  6. 如果遍历到的是特殊点n,则普通点数c1加一。
  7. 如果当前普通点数c1已经达到了k,说明到达该点的路径已经经过了k个普通点,需要停止从该点扩展路径搜索。
  8. 如果从当前节点temp到节点i的距离d[index][i]不超过r,且到达节点i的路径经过的普通点数c[i]大于当前普通点数c1,更新c[i]并将节点(i,c1,c2+1)加入队列,表示从当前节点到达节点i需要经过一个特殊点。
  9. 如果队列不为空,重复步骤3-8,直到找到终点或者队列为空为止。
int bfs(){
  queue<node> q;
  q.push((node){0,0,0});
  fill(c+1,c+n+m,k+1);
  while(!q.empty()){
    node temp=q.front();
    q.pop();
    int index=temp.id,c1=temp.cnt_n,c2=temp.cnt_t;
    if(index==1) return c2-1;
    for(int i=0;i<n+m;i++){
      if(i==n) c1++;
      if(c1>k) break;
      if(d[index][i]<=r && c1<c[i]){
        c[i]=c1;
        q.push((node){i,c1,c2+1});
      }
    } 
  }
}

2.代码

dev c++ 5.11

#include<bits/stdc++.h>
using namespace std;
const int N=200;
int n,m,k,r;
//x[i],y[i]存储所有路由器坐标,大于n时为新增路由器,c[i]表示从起点到i所经过的新增路由器的数量 
int x[N],y[N],c[N]={0};
//d[i][j]存储距离信息 
double d[N][N]={0};
//用于bfs, cnt_n表示经过的新增路由器数量, cnt_t表示经过的总的路由器数量 
struct node{
	int id,cnt_n,cnt_t;
};
double dist(int i,int j){
	double res=pow(1.0*x[i]-x[j], 2.0) + pow(1.0*y[i]-y[j], 2.0);
	return sqrt(res);
}
int bfs(){
	queue<node> q;
	q.push((node){0,0,0});
	fill(c+1,c+n+m,k+1);
	while(!q.empty()){
		node temp=q.front();
		q.pop();
		int index=temp.id,c1=temp.cnt_n,c2=temp.cnt_t;
		if(index==1) return c2-1;
		for(int i=0;i<n+m;i++){
			if(i==n) c1++;
			if(c1>k) break;
			if(d[index][i]<=r && c1<c[i]){
				c[i]=c1;
				q.push((node){i,c1,c2+1});
			}
		} 
	}
}
int main(){
	cin>>n>>m>>k>>r;
	for(int i=0;i<n+m;i++){
		cin>>x[i]>>y[i];
	}
	for(int i=0;i<n+m;i++){
		for(int j=i+1;j<n+m;j++){
			d[j][i]=d[i][j]=dist(i,j);
		}
	}
	cout<<bfs()<<endl;
	return 0;
}

该处使用的url网络请求的数据。


3.提交结果

结果

总结

综上,该算法使用了bfs来遍历有权图中的所有节点,找到从起点到终点的最短路径。通过限制从每个点出发经过的普通点数和距离,可以避免掉入死循环,同时保证算法的效率和正确性。

1.解释

  1. 利用对称矩阵存储距离信息,即把距离存储到 d[i][j] 和 d[j][i] 两个位置上。
for(int i=0;i<n+m;i++){
		for(int j=i+1;j<n+m;j++){
			d[j][i]=d[i][j]=dist(i,j);
		}
	}
  1. 初始化函数fill()。
    下面这段代码使用C++中的fill()函数,对从c+1索引开始的连续m+n个元素都赋值为k+1。其中:
  • c是指向数组首元素的指针;
  • m和n是两个整数;
  • k也是一个整数。
fill(c+1,c+n+m,k+1);

这段代码的作用是初始化一段长度为m+n,以指针c所指向的位置为起点的连续内存空间,将它们的值都设定为k+1。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值