CCF 无线网络

题意如下

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


这个题,怎么说呢,先上来看是懵逼的,直接被吓到了,感觉巨难,根本不知道怎么做,搜了搜题解也是各种解法,有的很长有的比较短,于是乎我就找了个短的开始研究,开始还是很痛苦的,一会也可以贴上大神的代码以及我读代码的时候加的注释,简直了。其中有一段可读性不好,让我理解了半天,最后理解了之后改变一下表达方式,果然清晰了很多。这题的主要思路是spfa,但是具体如何spfa是很有讲究的呀╮(╯▽╰)╭。读题的时候建图就把我吓到了,其实很简单,两重for循环,判断每个点之间的距离是不是小于规定的距离(这么暴力的法主要是怕超时),如果是,就说明两个点是联通的,直接让邻接矩阵的对应项赋值为1即可,图建好了,就可以进行spfa了。这里最有讲究的,就是d和vis数组,并不像平常的d和vis数组,代码中也有注释,即d[i][j]表示从起点开始,经过增设的j个点,到达第i个点的最短路径,vis[i][j]表示是否可以从起点经过增设的j个路由器到达i。其实看起来还不是很懂,但是实际上,这个d和平常的一维的d基本上没有任何区别,仍旧是表示从一个点到另一个点的距离,只是这里有判断到底经过了几个增设的点,然后后面的j的主要功能还是在松弛的时候判断是不是比规定的k个点多了,如果多了就直接不入队(啊,刚才看代码貌似还有一个用处,就是来表示经过不同数量的增设点可能有不同的距离,嗯,这点是很重要的)。vis数组的功能也和d差不多了。总之,这题真的看出思路和经验,方法又常规又巧妙,确实值得琢磨,也感受到自己与高手的实力差距。

以下是大神的简短代码以及我冗长的注释

//虽然被那两个题搞得有点不敢做题,但是比赛的时候该做还是要做的呀,毕竟如果思路对了的话
//再怎么说RP差也是会得分的吧 
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define N 205
#define INF 0x3f3f3f3f
typedef long long LL;
using namespace std;

struct P {
	int x,y;
} p[N];


int n,m,k,r;
int d[N][N];
bool vis[N][N],Map[N][N];

void spfa() {
	queue<P> q;
	memset(vis,0,sizeof(vis));
	memset(d,INF,sizeof(d));
	//这里的d[i][j]和vis[i][j]有特殊的含义
	// d[i][j]表示从起点开始,经过增设的j个点,到达第i个点的最短路径 
	// vis[i][j]表示是否可以从起点经过增设的j个路由器到达i
	d[0][0]=0; 
	vis[0][0]=1;
	//这里的s和tem感觉已经不再是表示一个点了,所以有点错觉 
	P s,tem;
	int des_p=0,ap_num=0; 
	int tp_des_p,tp_ap_num;
		s.x=s.y=des_p;
	q.push(s);
	while(!q.empty()) {
		s=q.front();
		q.pop();
		des_p=s.x;
		ap_num=s.y;
		vis[des_p][ap_num]=0;
		for(int i=0; i<n+m; ++i)
		//和s点相连的点 
		//另外看到这里莫名感觉这题简单(什么都不会,但有一种莫名的自信) 
		//这哪是spfa啊,更像是普通的bfs(写完我就后悔了= =) 
		//这里的s.x其实就是点的编号。程序可读性差= =(明明可以用别的表示的,非得图省事用P,差评!) 
		//嗯……这个程序有点带劲啊╮(╯▽╰)╭ 
			if(Map[des_p][i]) {
				//下面这几句是重点啊
				tp_des_p=i;
				tp_ap_num=ap_num;
				if(i>=n) ++tp_ap_num;
				if(tp_ap_num<=k && d[tp_des_p][tp_ap_num]>d[des_p][ap_num]+1) {
					//只要符合以上条件就进行松弛 
					d[tp_des_p][tp_ap_num]=d[des_p][ap_num]+1;
					//如果不在队列里就让其进入队列 
					if(!vis[tp_des_p][tp_ap_num]) {
						vis[tp_des_p][tp_ap_num]=1;
						//进入队列的其实是起点所到目的地点和经过的增设点数 
						tem.x=tp_des_p;
						tem.y=tp_ap_num;
						q.push(tem);
					}
				}
			}
	}
	int ans=INF;
	for(int i=0; i<=k; i++) ans=min(ans,d[1][i]);
	printf("%d\n",ans-1);
}

int main() {
	int i,j;
	cin>>n>>m>>k>>r;
	//输入存在的点和可以放置的点 
	for(i=0; i<n+m; ++i) scanf("%d%d",&p[i].x,&p[i].y);
	//map是邻接矩阵 
	memset(Map,0,sizeof(Map));
	//这个循环看起来不免重复,但是没超时 
	for(i=0; i<n+m; ++i)
		for(j=i+1; j<n+m; ++j)
		//LL就是long long int,这里是强制类型转换 
			if(LL(p[i].x-p[j].x)*(p[i].x-p[j].x)+LL(p[i].y-p[j].y)*(p[i].y-p[j].y)<=LL(r)*r)
				Map[i][j]=Map[j][i]=1;

	spfa();
	return 0;
}

其实本来不是这样的,本来是直接用的s.x和s.y来进行操作的,确实意思混淆了。另外,原谅我些许的逗比,毕竟学不会的时候是很蛋疼的。

然后下面是我的代码,虽然几乎是一样的,但毕竟是自己写哒,看起来亲切一些╮(╯▽╰)╭

另外解释下命名= =,des_p就是destination point的缩写,表示目的地点,ap_num就是 added point number的缩写(语法可能不太对= =),表示通过的增设点的数量

#include<iostream>
#include<queue>
#include<cstring>
#define MAX 100000001
#define N 205 
using namespace std;
typedef long long int LL;
int d[N][N];
bool vis[N][N];
bool arcs[N][N];
struct P{
	int x,y;
}p[N];

struct P_D{
	int des_p;
	int ap_num;
};
int m,n,k,r;
queue<struct P_D> q;
void spfa(){
	memset(d,MAX,sizeof(d));
	struct P_D s;
	struct P_D temp;
	s.des_p=0;
	s.ap_num=0;
	q.push(s);
	vis[0][0]=1;
	d[0][0]=0;
	while(!q.empty()){
		s=q.front();
		q.pop();
		vis[s.des_p][s.ap_num]=0;
		for(int i=0;i<n+m;i++)
			if(arcs[s.des_p][i]){
				temp.des_p=i;
				temp.ap_num=s.ap_num;
				if(i>=n) temp.ap_num++;
				if(temp.ap_num<=k && d[temp.des_p][temp.ap_num]>d[s.des_p][s.ap_num]+1){
					d[temp.des_p][temp.ap_num]=d[s.des_p][s.ap_num]+1;
					if(!vis[temp.des_p][temp.ap_num]){
						vis[temp.des_p][temp.ap_num]=1;
						q.push(temp);
					}
				}
			}
	}
	int ans=MAX;
	for(int i=0;i<=k;i++) ans=min(ans,d[1][i]);
	cout<<ans-1;
}

int main(){
	cin>>n>>m>>k>>r;
	for(int i=0;i<n+m;i++)
		cin>>p[i].x>>p[i].y;
	for(int i=0;i<n+m;i++)
		for(int j=i+1;j<n+m;j++)
			if( (LL)(p[i].x-p[j].x)*(p[i].x-p[j].x)+(LL)(p[i].y-p[j].y)*(p[i].y-p[j].y)<=(LL)r*r)
				arcs[i][j]=arcs[j][i]=1;
	spfa();	
	return 0;
}


### 回答1: CCF(中国计算机学会)会议是计算机网络领域的重要学术交流平台之一,每年都会举办多个与计算机网络相关的会议。以下是CCF会议在计算机网络领域的一些重要会议和举办时间: 1. 全球通信与信息系统会议(Globecom)- 该会议是CCF计算机网络领域最重要的国际会议之一。每年11月份在全球不同城市举办,包括了各种与通信和信息系统相关的主题。 2. 互联网计算与服务计算会议(ICSC)- 这个会议专注于互联网计算和服务计算领域的研究。一般每年5月或6月份在中国的某个城市举办。 3. 中文信息计算会议(CCIC)- 这是CCF计算机网络领域的一个独特的会议,通常会邀请中国地区的学者和业界专家分享中文信息计算领域的最新研究成果。会议时间一般安排在每年9月份。 4. 信息与系统安全会议(ISSC)- 这个会议侧重于研究信息安全和系统安全领域的最新进展。通常在每年的7月份在中国的某个城市举办。 除了以上提到的会议,CCF计算机网络领域还举办其他与无线网络、传感器网络、移动计算等相关的会议,如无线通信与移动计算会议(IWCMC)和无线传感器与互联网计算会议(WSWEC)。这些会议的具体时间表根据每年的安排可能会有所变化,因此建议关注CCF官方网站或相关学术论坛获取最新的会议时间表信息。 ### 回答2: CCF(中国计算机学会)是一个重要的计算机学术组织,定期举办国内外计算机领域的重要会议。以下是部分CCF会议的时间表: 1. CCF全国电子计算机等级考试论文答辩会(每年一次):一般在国内大城市举办,为电子计算机专业人才提供证书,提高计算机专业人员的素质和水平。 2. CCF中国计算机大会(每两年一次):这是CCF的旗舰会议,涵盖全面的计算机科学与技术领域。会议分为多个分论坛,包括人工智能、大数据、网络与通信等方向。此会议通常成为国内计算机科学领域学者展示研究成果和交流的重要平台。 3. CCF人工智能大会(每两年一次):CCF人工智能大会是国内规模最大的人工智能学术会议之一,拥有全球最高水平的AI专家和学者参与。会议包括人工智能前沿讲座、深度学习、自然语言处理、机器学习等重要方向的研讨会。 4. CCF云计算大会(每两年一次):云计算是当前计算机网络领域的热门话题之一,CCF云计算大会为专家学者提供了展示和分享最新研究成果的平台,涵盖云计算架构、安全性、大数据处理等相关议题。 此外,CCF还举办许多领域特定的会议,如CCF数据库会议、CCF网络与通信会议等,这些会议旨在促进学术交流,推动计算机科学与技术的发展。具体的时间表可以在CCF官网或相关学术平台上获取。 ### 回答3: CCF(中国计算机学会)会议是计算机网络领域重要的学术交流平台。CCF会议时间表包括多个排名不同的会议,主要分为A类会议和B类会议两大类。 CCF A类会议是计算机网络领域最顶级的会议,汇集了该领域内最顶尖的学者和专家。CCF A类会议具有严格的论文质量要求和学术评审过程。其中,最著名的会议有ICNP(国际计算机网络协议与应用会议)、INFOCOM(国际通信与网络会议)和SIGCOMM(ACM特别兴趣网络小组会议)等。这些会议每年固定在特定的时间段举办,通常在年初或年底进行,并且会轮流在国内外举行。 CCF B类会议相对于A类会议的学术影响力较弱,但仍然具备一定的学术价值和影响力。B类会议提供了更多的发表机会和交流平台,对于年轻学者和新兴研究方向的发展起到了重要的推动作用。CCF的B类会议主要有中国通信学会和中国电子学会共同举办的中国通信、中国电子学会(电子与通信分会)学术会议(CIC),以及中国计算机学会每年各个分会的学术会议等。 总之,CCF会议时间表涵盖了计算机网络领域内一系列重要的学术会议。这些会议为学者们提供了分享研究成果、交流学术观点的机会,进一步促进了计算机网络领域的学术发展和创新。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值