版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/88749767
【题目链接】
【思路要点】
- 考虑对于每一对点 ,求出 是否能到达 ,剩余部分可用 解决。
- 记 ,设水平速度为 ,竖直速度为 ,运动时间为 ,则有方程:
- 用 表示 代入 式,可得
- 由于我们希望 尽可能大从而避免撞在楼上,根据此式,我们需要求解最大的 ,从而得到一组使得 尽可能大的 。
- 检验是否撞在楼上只需要考虑处在楼房交界处的时候,可以单独考虑每一条交界处的线段,计算上述抛物线在对应位置的高度与楼房的高度进行比较即可。
- 时间复杂度 或 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 25; const int MAXM = 405; const double eps = 1e-7; const double g = 9.80665; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct point {double x, y; }; struct line {point a, b; }; point operator + (point a, point b) {return (point) {a.x + b.x, a.y + b.y}; } point operator - (point a, point b) {return (point) {a.x - b.x, a.y - b.y}; } point operator * (point a, double b) {return (point) {a.x * b, a.y * b}; } double operator * (point a, point b) {return a.x * b.y - a.y * b.x; } double moo(point a) {return sqrt(a.x * a.x + a.y * a.y); } double dis(point a, point b) {return moo(b - a); } point center[MAXN][MAXN]; double w, v; int n, m, height[MAXN][MAXN], dist[MAXN][MAXN]; pair <double, double> calspeed(int sx, int sy, int tx, int ty) { double d = w * sqrt((sx - tx) * (sx - tx) + (sy - ty) * (sy - ty)); double h = height[tx][ty] - height[sx][sy]; double a = g * g / 4, b = g * h - v * v, c = d * d + h * h; if (b * b - 4 * a * c < eps) return make_pair(-1, -1); double t = sqrt((-b + sqrt(b * b - 4 * a * c)) / (2 * a)); return make_pair(d / t, g * t / 2 + h / t); } bool check(line x, line y) { if (((y.a - x.a) * (x.b - x.a)) * ((y.b - x.a) * (x.b - x.a)) > eps) return false; if (((x.a - y.a) * (y.b - y.a)) * ((x.b - y.a) * (y.b - y.a)) > eps) return false; return true; } point inter(line x, line y) { double tmp = (y.a - x.a) * (y.b - x.a); double tnp = (y.b - x.b) * (y.a - x.b); return (x.a * tnp + x.b * tmp) * (1 / (tmp + tnp)); } bool reach(int sx, int sy, int tx, int ty) { pair <double, double> speed = calspeed(sx, sy, tx, ty); double x = speed.first, y = speed.second; if (x == -1 && y == -1) return false; line main = (line) {center[sx][sy], center[tx][ty]}; for (int i = min(sx, tx); i <= max(sx, tx); i++) for (int j = min(sy, ty); j <= max(sy, ty); j++) { point ru = (point) {(i - 1) * w, j * w}; point rd = (point) {i * w, j * w}; point ld = (point) {i * w, (j - 1) * w}; line r = (line) {ru, rd}, d = (line) {ld, rd}; if (check(r, main)) { double t = dis(inter(r, main), center[sx][sy]) / x; double h = y * t - g * t * t / 2 + height[sx][sy]; if (h < max(height[i][j], height[i][j + 1]) - eps) return false; } if (check(d, main)) { double t = dis(inter(d, main), center[sx][sy]) / x; double h = y * t - g * t * t / 2 + height[sx][sy]; if (h < max(height[i][j], height[i + 1][j]) - eps) return false; } } return true; } int main() { read(m), read(n), read(w), read(v); int sx, sy; read(sy), read(sx); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { read(height[i][j]); center[i][j] = (point) {(i - 0.5) * w, (j - 0.5) * w}; } memset(dist, -1, sizeof(dist)); deque <pair <int, int>> q; q.emplace_back(sx, sy), dist[sx][sy] = 0; while (!q.empty()) { int x = q.front().first; int y = q.front().second; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { if (dist[i][j] != -1) continue; if (reach(x, y, i, j)) { dist[i][j] = dist[x][y] + 1; q.emplace_back(i, j); } } q.pop_front(); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) if (dist[i][j] == -1) printf("X "); else printf("%d ", dist[i][j]); printf("\n"); } return 0; }