点击前往试题目录:https://blog.csdn.net/best335/article/details/99550556
考点:BFS
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,k,r,E[200][2],INF=0x7fffffff,LOG[200],N,dis[200][200];
int BFS(int v,int _k,int _d){
if(_k>k||_d>=LOG[v]) return INF;//超过满足题意的K或者已经遍历过
LOG[v]=_d;//记录v的最小遍历深度
int __d=_d+1,ans=INF,__k=_k+1;
//开始遍历所能到达的点 判断是否能够到达目的点
for(int i=1;i<n;++i){
if(dis[v][i]==-1)//计算 v i的距离 取上溢
dis[v][i]=dis[i][v]=ceil(sqrt(pow(abs(E[v][0]-E[i][0]),2.0)+pow(abs(E[v][1]-E[i][1]),2.0)));
if(dis[v][i]<=r&&LOG[i]>__d){
if(dis[i][1]==-1)
dis[1][i]=dis[i][1]=ceil(sqrt(pow(abs(E[1][0]-E[i][0]),2.0)+pow(abs(E[1][1]-E[i][1]),2.0)));
if(dis[i][1]<=r)
return __d;
}
}
if(__k<=k)//遍历可增设点
for(int i=n;i<N;++i){
if(dis[v][i]==-1)
dis[v][i]=dis[i][v]=ceil(sqrt(pow(abs(E[v][0]-E[i][0]),2.0)+pow(abs(E[v][1]-E[i][1]),2.0)));
if(dis[v][i]<=r&&LOG[i]>__d){
if(dis[i][1]==-1)
dis[1][i]=dis[i][1]=ceil(sqrt(pow(abs(E[1][0]-E[i][0]),2.0)+pow(abs(E[1][1]-E[i][1]),2.0)));
if(dis[i][1]<=r)
return __d;
}
}
//对所有的可到达点做BFS
for(int i=2,ni=__k>k?n:N;i<ni;++i){
if(dis[v][i]<=r)
ans=min(ans,BFS(i,i<n?_k:__k,__d));
}
return ans;
}
int main(){
cin>>n>>m>>k>>r;
memset(LOG,0x7f,sizeof(LOG));//初始化深度
memset(dis,-1,sizeof(dis));//初始化任意两点距离
for(int i=0,ni=N=n+m;i<ni;++i) cin>>E[i][0]>>E[i][1];//N=n+m E输入
cout<<BFS(0,0,0)<<endl;
return 0;
}
之前做的
#include <iostream>
#include <vector>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int n,m,k,N,ans; //题意n,m,k N=m+n ans结果
vector<vector<int> >vvi; //两点连接状态
unsigned long long r; //半径的平方
struct Point { int x,y; Point(int x=0,int y=0):x(x),y(y){} };
vector<Point>vP; //放置输入的路由器位置
vector<bool>global; //贪心连接 减少重复计算
vector<int>vQ,vQT,vK,vKT;//vQ同一深度放置的路由器 vK同一深度放置的路由器已增设的路由器个数 vQT下一深度路由器位置 vKT下一深度已增设
inline bool CanCall(const int& P1,const int& P2)
{
if (P1>P2) return CanCall(P2,P1);
if (vvi[P1][P2]!=-1) return vvi[P1][P2]==1;
unsigned long long a=abs(vP[P1].x-vP[P2].x),b=abs(vP[P1].y-vP[P2].y);
return (vvi[P1][P2]=(a*a+b*b<=r)?1:0)==1;
}
int main()
{
cin>>n>>m>>k>>r,r*=r,N=n+m,ans=0,vvi=vector<vector<int> >(N,vector<int>(N,-1));//处理输入
for (int i=0,x,y;i<n;++i) cin>>x>>y,vP.push_back(Point(x,y));
for (int i=0,x,y;i<m;++i) cin>>x>>y,vP.push_back(Point(x,y));//结束输入
if (CanCall(0, 1)) {cout<<0<<endl,vvi.clear(),vP.clear();return 0;}//如果两点直接可以连接 结束
global=vector<bool>(N,false);//初始化路由器放置状态
for (int i=2;i<N;++i) if (CanCall(0,i)) vQ.push_back(i),vK.push_back(0),global[i]=true;//如果路由器能够连接到第一个路由器 则加入到vQ中 并把K值初始化
while (vQ.size()>0)
{
++ans;//更新深度
for (int i=0,ni=vQ.size();i<ni;++i)//对该ans深度的所有的点进行遍历
{
if (CanCall(1,vQ[i])&&vK[i]<=k) {vQT.clear(),vQ.clear(),vK.clear(),vKT.clear();break;}//该点可以直接连接第二个路由器 结束 一定是最小值
for (int j=2;j<N;++j) if(!global[j]&&CanCall(vQ[i],j)) vQT.push_back(j),vKT.push_back(vK[i]+(j<n?0:1)),global[j]=true;//遍历所有的点若没有放置过,并且能够连接 vQ[i] 置放置状态 加入下一深度 加入K
}
vQ.clear(),vQ=vQT,vQT.clear(),vK.clear(),vK=vKT,vKT.clear();//更新下一深度路由信息
}
cout<<ans<<endl,vvi.clear(),vP.clear(),global.clear();//输出结果 清除占用内存
return 0;
}