题意:给你n个加油站的坐标,和起点终点坐标, 然后你开车用起点到终点, 你的车最多只能开L米,每经过一个加油站必定要加油,问你要加油几次。
先建图,跑个bfs即可,注意由于每经过一个加油站都要加油,所以路线不能重叠,所以要判一下斜率相等。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ex,ey,sx,sy,l;
int n,s,tt,dis[1005];
vector<int> ma[1005];
struct node
{
ll x,y;
} di[1005],tmp;
set<pair<ll,ll> > q;
ll get(int i,int j)
{
return (di[i].x-di[j].x)*(di[i].x-di[j].x)+(di[i].y-di[j].y)*(di[i].y-di[j].y);
}
bool cmp(node a,node b)
{
return a.x<b.x;
}
void bfs()
{
queue<int> qq;
qq.push(s);
memset(dis,-1,sizeof(dis));
dis[s]=0;
while(!qq.empty())
{
int cur=qq.front();
qq.pop();
for(int i=0; i<ma[cur].size(); i++)
{
int v=ma[cur][i];
if(dis[v]==-1)
{
dis[v]=dis[cur]+1;
if(tt==v)
{
printf("%d\n",dis[v]-1);
return;
}
qq.push(v);
}
}
}
puts("impossible");
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%I64d",&n,&l);
n+=2,q.clear(),l*=l;
for(int i=0;i<n;i++)
ma[i].clear();
scanf("%I64d%I64d%I64d%I64d",&sx,&sy,&ex,&ey);
di[0].x=sx,di[0].y=sy,di[1].x=ex,di[1].y=ey;
for(int i=2; i<n; i++)
scanf("%I64d%I64d",&di[i].x,&di[i].y);
sort(di,di+n,cmp);
for(int i=0; i<n; i++,q.clear())
{
if(di[i].x==sx&&di[i].y==sy)s=i;
if(di[i].x==ex&&di[i].y==ey)tt=i;
for(int j=i+1; j<n; j++)
{
ll len=get(i,j);
if(len>l) continue;
ll g=__gcd(di[i].x-di[j].x,di[i].y-di[j].y);
if(g<0) g=-g;
if(q.find({(di[i].x-di[j].x)/g,(di[i].y-di[j].y)/g})!=q.end())continue;
q.insert({(di[i].x-di[j].x)/g,(di[i].y-di[j].y)/g});
ma[i].push_back(j);
ma[j].push_back(i);
}
}
bfs();
}
}