CSP201403-4(无线网络)(Java 100分)

本文探讨了在一个平面房间内,如何通过增设新的无线路由器来优化已有的无线网络布局,以减少两个特定路由器间信号传输的中转次数。文章提供了一种算法实现思路,包括输入输出格式及Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

Java 代码 :

package csp201403;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
public class WirelessNet {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n=sc.nextInt();//目前在一个很大的平面房间里有 n 个无线路由器
		int m=sc.nextInt();//有 m 个可以摆放无线路由器的位置
		int k=sc.nextInt();//可以在这些位置中选择至多 k 个增设新的路由器。
		long r=sc.nextLong();//任何两个无线路由器只要距离不超过 r 就能互相建立网络连接
		Node node[]=new Node[n+m];//注意是n+m。
		for(int i=0;i<node.length;i++) {
			node[i]=new Node(sc.nextLong(),sc.nextLong(),i);
		}
		boolean vis[][]=new boolean[n+m][n+m];
		Queue<Node> q = new LinkedList<Node>();
		q.add(node[0]);
		while(!q.isEmpty()) {
			Node no=q.poll();
			int ti=no.time;
			int add=no.newAdd;
			int num=no.num;
			if(num==1) {//如果访问到第二个顶点(下标为1的顶点),则输出经过的中转路由器的个数。
				System.out.println(ti-1);
				return ;
			}
			for(int i=1;i<node.length;i++) {
				//循环从i=1开始。这个是有必要的,但是我描述不清楚,抱歉。当然,你从0开始遍历也可以,但是这样可以缩短程序运行时间
				if(node[i].distance(no)<=r&&num!=i) {
					//如果num!-i  因为加入poll出来的Node  假如num为5,而你计算node[5]到node[5]的距离是没用的,没有必要把自己加入队列,加入只会增加程序运行时间。
					if(vis[i][num]==true) {//如果num 点已经通过i点加入到队列中,那么应该continue
						continue;
					}
					if(i<n&&add<=k) {
						q.add(new Node(node[i].x,node[i].y,ti+1,add,i));
					}
					else if(i>=n&&add+1<=k){//如果i>=n,说明是新设的点,所以应该add+
						q.add(new Node(node[i].x,node[i].y,ti+1,add+1,i));
					}
					else {
						continue;
					}
					vis[i][num]=true;
					vis[num][i]=true;
				}
			}
		}
	}

}
class Node{
	int num;//编号
	long x;//x坐标
	long y;//y坐标
	int time;//已经走过的步数
	int newAdd;//到达这个点所经过的新设路由器
	public Node(long x, long y,int num) {
		this.num=num;
		this.x = x;
		this.y = y;
		time=0;
		newAdd=0;
	}
	public Node(long x, long y, int time, int newAdd,int num) {
		this.x = x;
		this.y = y;
		this.time = time;
		this.newAdd = newAdd;
		this.num=num;
	}
	public double distance(Node n) {
		long t1=n.x-x;
		long t2=n.y-y;
		return Math.sqrt(t1*t1+t2*t2);
	}
}

如果看不懂,那就调试吧。调试是最后的理解程序的方法。
用Eclipse调试的时候,按F5的话是程序运行下一行,但是如果下一行调用了函数,它会跳到函数里面。按F6的话,也是运行下一行,但是如果有程序调用,他不会跳到被调用的函数里面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值