最初のCCFコンピュータソフトウェアコンピテンシー認定
4番目の質問ワイヤレスネットワークspfa
注:最初にグラフを作成するとき、2つのポイント間の距離が爆発します
。intdis[i] [num]は、開始位置からポイントiまでの最短の長さを示し、num個の特別なポイントを通過します
。vis[i] [num]はのキューにあるかどうか
結果はmin [2] [kk]で、kk = 0〜k2が終点です。
#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;
}