CCFCSP-201403-4-无线网络

版权声明:欢迎读者提问交流。 个人水平有限,表述不当或疏漏之处敬请批评指正。 作者:trialley 来源:CSDN 著作权归作者所有。非商业转载请注明出处,商业转载请联系作者获得授权。 https://blog.csdn.net/lgfx21/article/details/89303911

 注:注释和BFS的条件判断部分都写得比较详细

我踩的坑:

  1. 提交时freopen与cout调试代码不注释
  2. scanf不智能,修改数据类型时无法自动适应
  3. 新状态push入队列时不能基于老状态修改,因为老状态需要重复使用
  4. 多个if嵌套便于理解逻辑
  5. 各种数据类型的范围
    1. char
    2. short
    3. int=long
    4. long long
    5. float
    6. double
    7. long double
试题编号: 201403-4
试题名称: 无线网络
时间限制: 1.0s
内存限制: 256.0MB
问题描述:

问题描述

  目前在一个很大的平面房间里有 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

#include<cmath>
#include<queue>
#include<math.h>
#include<cstring>
#include<iostream>
#include<cstdio>
#define ll double//long long则提交错误 
using namespace std;

/*点数组与图数组*/
ll point[250][2] = { 0 };
char graph[250][250] = { 0 };

typedef struct statu {
	int num = 0;//当前节点序号  
	int nk = 0;//访问过的未定点的个数
	int path = 0;//访问过的点的总个数,即步长 
}statu;
/*求两点间距离*/
ll distance(ll* a, ll* b) {
	return sqrt(pow((a[0] - b[0]), 2) + pow((a[1] - b[1]), 2));
}
int main() {

	/*信息输入 */
	int n; 
	int m;
	int k;
	ll r;
	//freopen("in.txt", "r", stdin);//调试代码注释则错误 
	cin >> n>>m>>k>>r;//输入信息少于10000条,使用cin (cin可以自动判断输入内容与目标变量的格式;scanf不那么智能,但是快 
	
	/*点信息输入,输入时一视同仁
	之后根据n与m确定哪些是已有点哪些是未定点*/
	for (int i = 0; i < (n + m); i++) {
		cin>>point[i][0]>>point[i][1];
	}


	/*计算每个点间的距离(包括两种点)
	距离只在这里有用,用完无需保存*/
	//由于距离的计算是相互的
	//因此j总是以i+1为初始值 
	for (int i = 0; i < n + m; i++) {
		for (int j = i + 1; j < n + m; j++) {
			if (distance(point[i], point[j]) <= r) {
				graph[i][j] = 1;
				graph[j][i] = 1;
			}
		}
	}

	/*广度优先搜索*/
	char visited[250] = { 0 };//访问标志 

	visited[0] = 1;

	statu now;
	now.nk = 0;
	queue<statu> q;
	q.push(now);

	int min = 100000;
	while (!q.empty()) {
		statu now = q.front();
		q.pop();


		//条件判断,如果只要求找到目标,则满足条件退出即可
		//如果要求求最值,则不能退出,要全部遍历 
		if (now.num == 1 && now.path < min) {
			min = now.path;
			//cout<<min<<endl;//调试代码未注释则错误 
		}


		//继续遍历连接的点,步数也加一 
		for (int i = 0; i < n + m; i++) {
		//	cout<<i<<endl;
			if(graph[now.num][i]==1){//如果连通 
				if(	!visited[i]){//如果点没有访问过 
					if(i<n){//如果是固定点 
						statu neww=now;//命名不能为c++关键词
						neww.path++;
						neww.num=i;
						q.push(neww);
						visited[i]=1;
					}else {//如果是不固定点 
						if(now.nk<k){//如果没有达到非固定上限 
							statu neww=now;//命名不能为c++关键词
							neww.nk++;
							neww.path++;
							neww.num=i;
							q.push(neww);
							visited[i]=1;		 
						} else{//达到非固定上限 
							continue; 
						}
					}
				}
			}
		}
	}
	//最后一个被访问的端点是终点,但题中说的是中间经过的路由地数,所以-1 
	cout<<min-1;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lgfx21/article/details/89303911