ACM International Collegiate Programming Contest Asia Regional Contest, Tokyo Problem D Space Golf

原题 pdf:click here


日本的亚洲区域赛真心简单啊。两个小时就刷了 5 题有余了。排名第一的队伍才做出 7 道。

题目真心长的可以了,看了半个小时才明白。。

题意其实也就是太空中向前方抛小球,问小球能够穿过 N 个障碍物后到达制定地点的最小初始速度是多少。非常暴力的模拟题。离散化后直接枚举弹跳的次数再取最小值即可。注意 45° 方向能成功的话,那还是 45° 最优。

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <cstdio>
#include <vector>
#include <cctype>
#include <cassert>
#include <utility>
#include <numeric>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr pair
#define PR pair<int, int>
#define MP make_pair
#define SI(x) set::iterator
#define VI(x) vector::iterator
#define MI(x, y) map<x, y>::iterator
#define SRI(x) set::reverse_iterator
#define VRI(x) vector::reverse_iterator
#define MRI(x, y) map<x, y>::reverse_iterator
#define F first
#define S second
#define Sz(x) (int)x.size()
#define clrQ(x)    \
  while (!x.empty) \
    x.pop();
#define clr(x, y) memset(x, y, sizeof(x));
#if defined(_WIN32) || defined(__WIN32) || defined(WIN32) || defined(__WIN32__)
#define LL __int64
#define LLS "%" \
            "I" \
            "6" \
            "4" \
            "d"
#define LLU "%" \
            "I" \
            "6" \
            "4" \
            "u"
#define LL_MAX _I64_MAX
#else
#define LL long long
#define LLS "%" \
            "l" \
            "l" \
            "d"
#define LLU "%" \
            "l" \
            "l" \
            "u"
#define LL_MAX _I64_MAX
#endif
const int inf = ~0u >> 1;
const LL lnf = ~0ull >> 1;
#define eps 1e-8
/*start*/
int d, n, b;
PR ob[20];
vector<pair<double, double>> vt;
pair<double, double> dpr;
double a[2][2], e[2];
pair<double, double> Cramer(pair<double, double> dpr)
{
  pair<double, double> res;
  a[1][0] = dpr.F * dpr.F;
  a[1][1] = dpr.F;
  e[1] = dpr.S;
  double div = a[0][0] * a[1][1] - a[1][0] * a[0][1];
  res.F = (e[0] * a[1][1] - e[1] * a[0][1]) / div;
  res.S = (e[1] * a[0][0] - e[0] * a[1][0]) / div;
  return res;
}
int main(int argc, char **argv)
{
  while (~scanf("%d%d%d", &d, &n, &b))
  {
    for (int i = 0; i < n; i++)
    {
      scanf("%d%d", &ob[i].F, &ob[i].S);
    }
    double ans = inf;
    for (int c = 0; c <= b; c++)
    { //enumerate the times bullet bounces the surface
      double dist = 1.0 * d / (c + 1);
      int f = 1;
      a[0][0] = dist * dist;
      a[0][1] = dist;
      e[0] = 0;
      vt.clear();
      for (int i = 0; i < n; i++)
      {
        dpr = ob[i];
        while (dpr.F + eps >= dist)
        {
          dpr.F -= dist;
        }
        if (dpr.F <= eps)
        {
          f = 0;
          break;
        }
        vt.push_back(dpr);
      }
      if (f == 0)
        continue;
      pair<double, double> res;
      for (int i = 0; i < Sz(vt); i++)
      {
        dpr = vt[i];
        if (i == 0)
        {
          res = Cramer(dpr);
        }
        else
        {
          double tmph = dpr.F * dpr.F * res.F + dpr.F * res.S;
          if (tmph + eps < dpr.S)
          {
            res = Cramer(dpr);
          }
        }
      }
      res.F = -1.0 / (2 * res.F);
      res.S = res.F * res.S * res.S;
      ans = min(ans, sqrt(res.F + res.S));
      //if the vector's angle is less than 45
      if (res.S + eps < res.F)
        ans = min(ans, sqrt(dist));
    }
    printf("%.5f", ans);
  }
}

Comments