注意:初始构建图的时候,两点距离会爆int
dis[i][num]表示从起始位置到i点且经过num个特殊点的最短路长度
vis[i][num]表示是否在队列中
结果即是min[2][kk],kk=0~k 2为终点
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#include<queue>
typedef long long LL;
typedef pair<int,int> PII;
const int max_n=210;
const int max_m=210*210;
int bes_dis=0x1f1f1f1f;
int dis[max_n][105];
int vis[max_n][105];
int kind[max_n];
int beg,endd;
int idx;
int h[max_n];
int ne[max_m];
int e[max_m];
int n,m,k;
LL r;
struct Point{
int x,y;
}PP[max_n];
void add(int u,int v)
{
e[idx]=v;
ne[idx]=h[u];
h[u]=idx++;
}
queue<PII> qq;
int dd(int u,int v)
{
if(LL(PP[u].x-PP[v].x)*(PP[u].x-PP[v].x)+LL(PP[u].y-PP[v].y)*(PP[u].y-PP[v].y)<=r*r )
return 1;
else return 0;
}
void init()
{
memset(h,-1,sizeof(h));
}
void spfa()
{
memset(dis,0x1f1f1f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[beg][0]=0;
vis[beg][0]=1;
qq.push({
beg,0});
while(!qq.empty())
{
PII tt=qq.front();
qq.pop();
vis[tt.first][tt.second]=0;//出队 vis变为0
int next,next_num;
for(int i=h[tt.first];~i;i=ne[i])
{
next=e[i];
if(kind[next])
next_num=tt.second+1;
else next_num=tt.second;
if(next_num<=k && dis[next][next_num]>dis[tt.first][tt.second]+1) //<=k进行减枝
{
dis[next][next_num]=dis[tt.first][tt.second]+1;
if(!vis[next][next_num]) //更新距离和进队不完全同步
{
qq.push({
next,next_num});
vis[next][next_num]=1;
}
}
}
}
int minn=0x1f1f1f1f;
for(int i=0;i<=k;i++)
{
minn=min(minn,dis[endd][i]);
}
cout<<minn-1;
}
int main()
{
cin>>n>>m>>k>>r;
beg=1;
endd=2;
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d",&PP[i].x,&PP[i].y);
kind[i]=0;
for(int j=1;j<i;j++)
{
if(dd(i,j))
{
add(i,j);
add(j,i);
}
}
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&PP[i+n].x,&PP[i+n].y);
kind[i+n]=1;
for(int j=1;j<i+n;j++)
{
if(dd(i+n,j))
{
add(i+n,j);
add(j,i+n);
}
}
}
spfa();
return 0;
}