第二次CCF-4-无线网络(二维最短路-spfa)


问题描述
试题编号: 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 ≤ 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

题解:做这题的时候想到了使用广搜,但是各种小问题无法解决,后来看了题解,发现巨巨的
二维最短路,真的很巧,这里仿照写了一发。。
dp[i][j]:终点为i用到j个外加路由器的最短路径。
vis[i][j]:起相应的标记作用。
代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<limits.h>
#include<iostream>
#include<queue>
#include<string>
#include<cstdio>
#include<cstring>
#include<stack>
#include<vector>
#include<math.h>
#include<map>
using namespace std;
#define maxn 205
#define INF 0x3f3f3f3f 
int dp[maxn][maxn],Map[	maxn][maxn];
bool vis[maxn][maxn];
int n,m,k,r;
struct node
{
	int x,y;
}a[maxn];
struct road
{
	int dis,num;
};
queue<road>q;
void spfa()
{
	int i,j;
	road s;
	dp[1][0]=0;
	s.dis=1;
	s.num=0;
	q.push(s);
	while(!q.empty())
	{
		road now=q.front();
		q.pop();
		vis[now.dis][now.num]=0;
		for(i=1;i<=n+m;i++)
		{
			if(Map[now.dis][i])
			{
				road nexts;
				nexts.num=now.num;
				nexts.dis=i;
				if(i>n)nexts.num++;
				if(nexts.num<=k && dp[nexts.dis][nexts.num]>dp[now.dis][now.num]+1)
				{
					dp[nexts.dis][nexts.num]=dp[now.dis][now.num]+1;
					if(!vis[nexts.dis][nexts.num])
					{
						vis[nexts.dis][nexts.num]=1;
						q.push(nexts);
					}
				}
			}
		}
	}
	int ans=INF;
	for(i=0;i<=k;i++)
	  ans=min(ans,dp[2][i]);
	printf("%d\n",ans-1);
}
int main()
{
	memset(Map,0,sizeof(Map));
	memset(vis,0,sizeof(vis));
	memset(dp,INF,sizeof(dp));
	int i,j;
	scanf("%d%d%d%d",&n,&m,&k,&r);
	for(i=1;i<=n+m;i++)
	  scanf("%d%d",&a[i].x,&a[i].y);
	for(i=1;i<n+m;i++)
	  for(j=i+1;j<=n+m;j++)
	    if((long long)(a[i].x-a[j].x)*(a[i].x-a[j].x)+(long long)(a[i].y-a[j].y)*(a[i].y-a[j].y)<=(long long)(r)*r)
	         Map[i][j]=Map[j][i]=1;
	spfa();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值