题意:给你一个W×L的网格,有一个起点和一个终点,你在起点的速度是零,加速度是a,有一些点有速度限制vp,全程有一个最大速度限制vm,问你从起点到终点的最短时间是多少。
思路:由于从起点到终点要不直接到达,要不经过一些限速点,所以预处理出起点和其他限速点直接相邻的点,建图,跑最短路即可。两点之间的最短时间用高中物理的知识可以解决。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 100 + 10;
const int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
const int INF = 0x3f3f3f3f;
const int maxe = 20000 + 100;
const double eps = 1e-8;
typedef pair<int, int> pill;
struct Edge{
int v, next;
double d;
Edge(int v = 0, double d = 0, int next = 0) : v(v), d(d), next(next) {}
};
struct HeapNode{
int v;
double min_time;
HeapNode(int v, double min_time) : v(v), min_time(min_time) {}
HeapNode() {}
bool operator < (const HeapNode &rhs) const{
return min_time > rhs.min_time;
}
};
int n, W, L;
double a, vm, vp;
pill pos[maxn];
int vis[maxn][maxn];//0 st 1 ed >=2 police
int vis2[maxn][maxn];
vector<int> neighbor;
int d[maxn], Head[maxn], cntE;
Edge edge[maxe];
bool judge(int x, int y){
if(x >= 0 && x <= W && y >= 0 && y <= L)
return true;
return false;
}
struct Work{
int x, y;
int step;
Work(int x, int y, int step) : x(x), y(y), step(step) {}
Work() {}
};
void bfs(int x, int y, int cu){
Work st(x, y, 0);
queue<Work> Q;
Q.push(st);
d[cu] = 0;
while(!Q.empty()){
Work cur = Q.front(); Q.pop();
int xx = cur.x;
int yy = cur.y;
if(vis2[xx][yy]) continue;
vis2[xx][yy] = 1;
int step = cur.step;
if(vis[xx][yy] && vis[xx][yy] != cu){
d[vis[xx][yy]] = step;
neighbor.push_back(vis[xx][yy]);
continue;
}
for(int i = 0; i < 4; i++){
int dx = xx + dir[i][0];
int dy = yy + dir[i][1];
if(!judge(dx, dy) || vis2[dx][dy]) continue;
Q.push(Work(dx, dy, step + 1));
}
}
}
void init(){
memset(Head, -1, sizeof(Head));
cntE = 0;
}
void add(int u, int v, int d){
edge[cntE] = Edge(v, double(d), Head[u]);
Head[u] = cntE++;
}
double get_time(double v0, double vt, double s, double &vf){
double t1 = (vt - v0) / a;
if(v0 * t1 + a * t1 * t1 / 2 >= s){
double ans = (sqrt(v0 * v0 + 2 * a * s) - v0) / a;
vf = v0 + a * ans;
return ans;
}
else{
double len = (2 * vm * vm - v0 * v0 - vt * vt) / 2 / a, vx;
vf = vt;
if(len > s){
vx = sqrt((2 * a * s + v0 * v0 + vt * vt) / 2);
return (2 * vx - v0 - vt) / a;
}
else{
return (2 * vm - v0 - vt) / a + (s - (2 * vm * vm - v0 * v0 - vt * vt) / 2 / a) / vm;
}
}
}
double dist[maxn], cur_v[maxn];
void dijkstra(){
double ddd;
for(int i = 0; i < n + 3; i++) dist[i] = double(INF);
dist[1] = 0;
priority_queue<HeapNode> Q;
Q.push(HeapNode(1, 0));
while(!Q.empty()){
HeapNode cur = Q.top(); Q.pop();
int u = cur.v;
double t = cur.min_time;
for(int i = Head[u]; ~i; i = edge[i].next){
int v = edge[i].v;
double v0, vt, vf;
v0 = cur_v[u];
if(v > 2) vt = vp;//is police
else vt = vm;
double tt = get_time(v0, vt, edge[i].d, vf);
if(dist[v] > dist[u] + tt){
dist[v] = dist[u] + tt;
cur_v[v] = vf;
Q.push(HeapNode(v, dist[v]));
}
}
}
}
int main()
{
scanf("%d%d%d%lf%lf%lf", &W, &L, &n, &a, &vm, &vp);
if(vm < vp) vp = vm;
scanf("%d%d%d%d", &pos[1].first, &pos[1].second, &pos[2].first, &pos[2].second);
vis[pos[1].first][pos[1].second] = 1;
vis[pos[2].first][pos[2].second] = 2;
for(int i = 3; i < n + 3; i++){
int x, y;
scanf("%d%d", &x, &y);
pos[i].first = x;
pos[i].second = y;
vis[x][y] = i;
}
init();
for(int i = 1; i < n + 3; i++){
int x = pos[i].first;
int y = pos[i].second;
memset(vis2, 0, sizeof(vis2));
memset(d, INF, sizeof(d));
neighbor.clear();
bfs(x, y, i);
for(int j = 0; j < (int)neighbor.size(); j++){
add(i, neighbor[j], d[neighbor[j]]);
}
}
dijkstra();
printf("%.10lf\n", dist[2]);
return 0;
}