H. Information Transmission-3 Time Limit: 2000MS There is n bases in a certain area, numbered 1, 2,. .. .. , n, the location of base i is represented by coordinates (xi, yi). Dr. Kong is at point (x1, y1), he must send an information to point (xn, yn). Because of the insecurity of the network, he decided to drive the information in person. When he is ready to leave, he find that there is something wrong with the steering wheel of his car. The steering wheel can only turn right and can not turn left.
All roads in the area are known . If there is a road from base i to base j, the path length of the road is calculated from the coordinates sqrt((xi-xj)2 +(yi-yj)2) , assuming that all roads are two-way. At first, Dr. Kong may choose any road to set off from base 1. Once he leaves, he can only go straight or turn right at a given coordinate point. For faster transmission of information , Can you help Dr. Kong design a shortest path from Base 1 to Base n without turning left on the steering wheel?
Input
The first line of the input contains one integer T, which is the number of test cases (1<=T<=5). Each test case specifity:
* Line 1: n m n bases, m roads ( 1 ≤ n≤ 100, 1 ≤ m≤ 200 )
* Line 2~n+1: xi yi the location of base i ( 2 integers, 0 ≤ xi , y i ≤ 1000 )
* Line n+2~n+m+1: ik jk there is a road from base ik to base jk
Output
For each test case generate a single line: a real number, the shortest path from Base 1 to Base n without turning left on the steering wheel. accurate to 2 decimal places.
Sample Input | |
1 5 6 10 10 10 5 30 5 12 30 15 0 1 2 2 5 3 5 1 3 1 4 4 5 | 36.43 |
题目大意 :有N个地点, 从1出发到N, 每次只能直走或者往右走 (极坐标下的顺时针), 输出1到 N的最短路
思路 : 只能靠右走, 可以利用向量来做, 如果两个向量 a 和 b的 叉积 < 0, 数目a向量 在b向量的逆时针方向上, 逆时针也就是题目所说的方向盘必须直打或者往右打。 所以在跑最短路的时候可以维护上一个走过的点和当前的点, 如果这两个点和下一个点满足上述关系, 并且有更短的路可以走, 就更新, 由于点1没有上一个点, 所以把和1相连的所有点全部加入队列, 这样1就成了他们的上一个点, 再把1初始化一下, 就解决了
Accepted code
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 10;
const int INF = 0x3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }
struct Edge
{
int v, next;
double w;
}e[MAXN << 1];
struct node
{
int last, id; double w;
bool operator < (const node &oth) const
{
return w > oth.w;
}
}mid;
struct point
{
double x, y;
}p[MAXN];
int head[MAXN], n, m, cnt, T;
double dis[MAXN];
bool vis[MAXN];
void init() {
MEM(head, -1); cnt = 0;
}
void add(int from, int to, double wi) {
e[++cnt].v = to;
e[cnt].w = wi;
e[cnt].next = head[from];
head[from] = cnt;
}
double Cross(point a, point b, point c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); // 叉积
}
void dijkstra(int u) {
priority_queue <node> q;
for (int i = 1; i <= n; i++) dis[i] = INF * 1.0, vis[i] = 0;
for (int i = head[1]; i != -1; i = e[i].next)
q.push({ 1, e[i].v, e[i].w }), dis[e[i].v] = e[i].w; // 与1相连加入队列
vis[1] = 1; dis[1] = 0; // 1不要了
while (!q.empty()) {
mid = q.top();
q.pop();
int ans = mid.id, last = mid.last;
if (vis[ans] || dis[ans] != mid.w) continue;
vis[ans] = 1;
for (int i = head[ans]; i != -1; i = e[i].next) {
int vi = e[i].v;
double tmp = Cross(p[last], p[ans], p[vi]); // 叉积小于等于0
if (tmp <= 0 && dis[vi] > dis[ans] + e[i].w) {
dis[vi] = dis[ans] + e[i].w;
q.push({ ans, vi, dis[vi] });
}
}
}
}
int main()
{
cin >> T;
while (T--) {
sc("%d %d", &n, &m); init();
for (int i = 1; i <= n; i++) sc("%lf %lf", &p[i].x, &p[i].y);
for (int i = 0; i < m; i++) {
int ui, vi;
sc("%d %d", &ui, &vi);
double tmp = sqrt(P2(p[ui].x - p[vi].x) + P2(p[ui].y - p[vi].y));
add(ui, vi, tmp); add(vi, ui, tmp);
}
dijkstra(1);
printf("%.2f\n", dis[n]);
}
return 0;
}