HDU 4885 Bestcoder#2-1003 TIANKENG’s travel 【判断三点共线建图 + 最短路bfs】http://acm.hdu.edu.cn/showproblem.php?pid=4885
Problem Description
TIANKENG has get a driving license and one day he is so lucky to find a car. Every day he drives the car around the city. After a month TIANKENG finds that he has got high driving skills and he wants to drive home. Assuming that we regard the map of Hangzhou as a two-dimensional Cartesian coordinate system, the coordinate of the school is (sx, sy), the coordinate of TIANKENG’s home is (ex,ey). There are n gas stations distributing along the road and the coordinate of the ith gas station is (xi, yi). Because there is something wrong with the car engine, TIANKENG can drive the car for L miles after every time he fills up the gas. Assuming that TIANKENG must fill up the gas when he passes by a gas station and the initial status of the tank is full. TIANKENG must drive on the straight line and he can only choose to drive to school or home or gas station. Your task is to tell TIANKENG the minimum times he needs to charge fuel to go home successfully.
Input
The first line contains a positive integer T(T<=30), referring to T test cases.
For each test case, the first line contains two integers n(0<=n<=1000), L(1<=L<=100000), which mean n gas stations in all and the distance TIANKENG can drive with the full tank respectively. The second line contains two integers sx, sy, which refers to the coordinate of the school.
The third line contains two integers ex, ey, which refers to the coordinate of TIANKENG’s home.
Then following n lines, each line contains two integer xi, yi, which refers to the coordinate of gas station.
Assuming that all the coordinates are different! All the coordinates satisfied [0,1000000].
For each test case, the first line contains two integers n(0<=n<=1000), L(1<=L<=100000), which mean n gas stations in all and the distance TIANKENG can drive with the full tank respectively. The second line contains two integers sx, sy, which refers to the coordinate of the school.
The third line contains two integers ex, ey, which refers to the coordinate of TIANKENG’s home.
Then following n lines, each line contains two integer xi, yi, which refers to the coordinate of gas station.
Assuming that all the coordinates are different! All the coordinates satisfied [0,1000000].
Output
For each test case, if TIANKENG cannot go home successfully, print “impossible”(without quotes), otherwise print the minimum times of charging fuel.
Sample Input
2 2 1000 0 0 2000 1000 1000 0 2000 0 0 1000 0 0 2000 1000
Sample Output
2 impossible
Source
【思路】先建图,建图时把两点中间没有点,并且距离能到达的建一条长度1的边,那么问题就是如何判断中间没有点,先把所有点按x排序,然后每次找的时候,利用一个set存放当前已有向量,那么下次如果又出现肯定就是不能加入的点,利用set去搞,然后建完图就是简单的广搜了
【代码如下】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdlib>
#include <set>
#include <algorithm>
using namespace std;
const int N = 2000;
vector<int> g[N];
int t, n, vis[N];
long long L;
struct point
{
long long x,y;
int id;
}p[N];
bool cmp(point a, point b)
{
if(a.x != b.x) return a.x < b.x;
return a.y < b.y;
}
long long gcd(long long a, long long b)
{
if(!b) return a;
return gcd(b, a%b);
}
bool dis(point a, point b){
long long dx = a.x - b.x;
long long dy = a.y - b.y;
return dx*dx + dy*dy <= L*L;
}
void build()
{
sort(p, p+n+1, cmp);
for(int i=0; i<=n+1; i++)
{
set<pair<int, int> > save;
for(int j=i+1; j<=n+1; j++)
{
if(dis(p[i], p[j]))
{
long long dx = p[i].x - p[j].x;
long long dy = p[i].y - p[j].y;
long long d = gcd(dx, dy);
dx /= d; dy /= d;
if(save.find(make_pair(dx, dy)) != save.end())
continue;
save.insert(make_pair(dx, dy));
g[p[i].id].push_back(p[j].id);
g[p[j].id].push_back(p[i].id);
}
}
}
}
bool solve()
{
queue<int> Q;
memset(vis, -1, sizeof(vis));
Q.push(0);
vis[0] = 0;
while(!Q.empty())
{
int now = Q.front();
if(now == n+1){
printf("%d\n",vis[now]-1);
return true;
}
Q.pop();
for(int i=0; i<g[now].size(); i++)
{
int v = g[now][i];
if(vis[v] != -1)
continue;
vis[v] = vis[now]+1;
Q.push(v);
}
}
return false;
}
int main()
{
cin>>t;
while(t--)
{
scanf("%d %lld", &n, &L);
scanf("%lld %lld", &p[0].x, &p[0].y);
p[0].id = 0; p[n+1].id = n+1;
scanf("%lld %lld", &p[n+1].x, &p[n+1].y);
g[0].clear(); g[n+1].clear();
for(int i=1; i<=n; i++){
g[i].clear();
scanf("%lld %lld", &p[i].x, &p[i].y);
p[i].id = i;
}
build();
if(!solve())
printf("impossible\n");
}
return 0;
}