Problem p01204 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int dy[] = {-1, 0, 1, 0}, dx[] = {0, 1, 0, -1};
// adjust problem by problem
const double EPS = 1e-8;
const double PI = acos(-1.0);
#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#ifdef __GNUC__
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
int popcount(int n) { return __builtin_popcount(n); }
int popcount(ll n) { return __builtin_popcountll(n); }
#endif
#ifndef __GNUC__
template <class T> int popcount(T val) {
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  val = (val + (val >> 4)) & 0x0f0f0f0f;
  val += val >> 8;
  val += val >> 16;
  return (int)(val & 0x0000003f);
}
#endif
template <class T> int SIZE(T a) { return a.size(); }
template <class T> string IntToString(T num) {
  string res;
  stringstream ss;
  ss << num;
  return ss.str();
}
template <class T> T StringToInt(string str) {
  T res = 0;
  for (int i = 0; i < SIZE(str); i++)
    res = (res * 10 + str[i] - '0');
  return res;
}
template <class T> T gcd(T a, T b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
template <class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template <class T> void PrintSeq(T &a, int sz) {
  for (int i = 0; i < sz; i++) {
    cout << a[i];
    if (sz == i + 1)
      cout << endl;
    else
      cout << ' ';
  }
}
ll getTen(int a) { return (a <= 0) ? 1 : (getTen(a - 1) * 10); }
bool EQ(double a, double b) { return abs(a - b) < EPS; }
void fastStream() {
  cin.tie(0);
  std::ios_base::sync_with_stdio(0);
}
vector<string> split(string str, char del) {
  vector<string> res;
  for (int i = 0, s = 0; i < SIZE(str); i++) {
    if (str[i] == del) {
      if (i - s != 0)
        res.push_back(str.substr(s, i - s));
      s = i + 1;
    } else if (i == SIZE(str) - 1) {
      res.push_back(str.substr(s));
    }
  }
  return res;
}

int N;
double sy, sx, sz;
double gy, gx, gz;
double px[101][2];
double py[101][2];
double pz[101][2];
double d[101][101];

// 線分と点の間の距離を計算(3次元)
double calcDist(double x0, double y0, double z0, double x1, double y1,
                double z1, double px, double py, double pz) {
  double res = 0;
  double dy = y1 - y0;
  double dz = z1 - z0;
  double dx = x1 - x0;
  double a = dx * dx + dy * dy + dz * dz;
  double b = dx * x0 + dy * y0 + dz * z0;
  double c = (dx * px + dy * py + dz * pz);
  double t = 0;
  if (!EQ(a, 0))
    t = (c - b) / a;
  double ox = x0 + dx * t;
  double oy = y0 + dy * t;
  double oz = z0 + dz * t;
  res = sqrt((ox - px) * (ox - px) + (oy - py) * (oy - py) +
             (oz - pz) * (oz - pz));
  return res;
}

double calcDist(double x0, double y0, double z0, double x1, double y1,
                double z1, double x2, double y2, double z2, double x3,
                double y3, double z3) {
  double res = 0;
  double a1 =
      (x3 - x2) * (x1 - x0) + (y3 - y2) * (y1 - y0) + (z3 - z2) * (z1 - z0);
  double a2 =
      (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0);
  double a3 =
      (x1 - x0) * (x2 - x0) + (y1 - y0) * (y2 - y0) + (z1 - z0) * (z2 - z0);
  double b1 =
      (x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2) + (z3 - z2) * (z3 - z2);
  double b2 =
      (x1 - x0) * (x3 - x2) + (y1 - y0) * (y3 - y2) + (z1 - z0) * (z3 - z2);
  double b3 =
      (x3 - x2) * (x2 - x0) + (y3 - y2) * (y2 - y0) + (z3 - z2) * (z2 - z0);
  double t, s;
  // cout<<a1<<" "<<a2<<" "<<a3<<" ";
  // cout<<b1<<" "<<b2<<" "<<b3<<endl;
  if (a1 == 0) {
    t = a3 / a2;
    s = (t * b2 - b3) / b1;
  } else if (a2 == 0) {
    s = -a3 / a1;
    t = (s * b1 + b3) / b2;
  } else if (b1 == 0) {
    t = b3 / b2;
    s = (t * a2 - a3) / a1;
  } else if (b2 == 0) {
    s = -b3 / b1;
    t = (s * a1 + a3) / a2;
  } else {
    if (a2 * b1 - a1 * b2 == 0)
      t = 0;
    else
      t = (a3 * b1 - a1 * b3) / (a2 * b1 - a1 * b2);
    s = (t * a2 - a3) / a1;
  }

  double p1x = x0 + t * (x1 - x0);
  double p1y = y0 + t * (y1 - y0);
  double p1z = z0 + t * (z1 - z0);

  double p2x = x2 + s * (x3 - x2);
  double p2y = y2 + s * (y3 - y2);
  double p2z = z2 + s * (z3 - z2);

  res = sqrt((p1x - p2x) * (p1x - p2x) + (p1y - p2y) * (p1y - p2y) +
             (p1z - p2z) * (p1z - p2z));

  return res;
}

struct Point {
  double x, y, z;
  Point(double x_, double y_, double z_) {
    x = x_;
    y = y_;
    z = z_;
  }
  Point() {}
};

Point cross(Point p1, Point p2) {
  return Point(p1.y * p2.z - p1.z * p2.y, p1.z * p2.x - p1.x * p2.z,
               p1.x * p2.y - p1.y * p2.x);
}
double dot(Point p1, Point p2) {
  return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
}
double abs(Point p) { return sqrt(p.x * p.x + p.y * p.y + p.z * p.z); }

/*
  線分間距離ではなく、直線間距離を計算
 */

int main() {

  while (cin >> N && N) {
    cin >> sx >> sy >> sz >> gx >> gy >> gz;
    for (int i = 0; i < N; i++)
      for (int j = 0; j < 2; j++)
        cin >> px[i][j] >> py[i][j] >> pz[i][j];
    // すべての線分間の距離を計算
    for (int i = 0; i < N; i++) {
      for (int j = i; j < N; j++) {
        if (i == j)
          d[i][j] = 0;
        else {
          d[j][i] = d[i][j] = calcDist(px[i][0], py[i][0], pz[i][0], px[i][1],
                                       py[i][1], pz[i][1], px[j][0], py[j][0],
                                       pz[j][0], px[j][1], py[j][1], pz[j][1]);
        }
      }
    }
    for (int k = 0; k < N; k++)
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
          d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    // double res=1e+15;
    //  // sy,sx,szとgx,gy,gzの２点がどのノード上に乗っているか調べる
    //  for(int i=0;i<N;i++){
    //    for(int j=0;j<N;j++){
    //      double
    //      dist=calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],sx,sy,sz);
    //      //cout<<i<<" "<<j<<" "<<dist<<endl;
    //      dist+=calcDist(px[j][0],py[j][0],pz[j][0],px[j][1],py[j][1],pz[j][1],gx,gy,gz);
    //      dist+=d[i][j];
    //      res=min(res,dist);
    //    }
    //  }
    // printf("%.10f\\n",res);
    int spos = -1, gpos = -1;
    for (int i = 0; i < N; i++) {
      if (EQ(0, calcDist(px[i][0], py[i][0], pz[i][0], px[i][1], py[i][1],
                         pz[i][1], sx, sy, sz)))
        spos = i;
      if (EQ(0, calcDist(px[i][0], py[i][0], pz[i][0], px[i][1], py[i][1],
                         pz[i][1], gx, gy, gz)))
        gpos = i;
    }
    // cout<<spos<<" "<<gpos<<endl;
    printf("%.10f\\n", d[spos][gpos]);
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
const int dy[] = {-1, 0, 1, 0}, dx[] = {0, 1, 0, -1};
// adjust problem by problem
const double EPS = 1e-8;
const double PI = acos(-1.0);
#define REP(i, n) for (int i = 0; i < (int)n; ++i)
#ifdef __GNUC__
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
int popcount(int n) { return __builtin_popcount(n); }
int popcount(ll n) { return __builtin_popcountll(n); }
#endif
#ifndef __GNUC__
template <class T> int popcount(T val) {
  val = val - ((val >> 1) & 0x55555555);
  val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  val = (val + (val >> 4)) & 0x0f0f0f0f;
  val += val >> 8;
  val += val >> 16;
  return (int)(val & 0x0000003f);
}
#endif
template <class T> int SIZE(T a) { return a.size(); }
template <class T> string IntToString(T num) {
  string res;
  stringstream ss;
  ss << num;
  return ss.str();
}
template <class T> T StringToInt(string str) {
  T res = 0;
  for (int i = 0; i < SIZE(str); i++)
    res = (res * 10 + str[i] - '0');
  return res;
}
template <class T> T gcd(T a, T b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
template <class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template <class T> void PrintSeq(T &a, int sz) {
  for (int i = 0; i < sz; i++) {
    cout << a[i];
    if (sz == i + 1)
      cout << endl;
    else
      cout << ' ';
  }
}
ll getTen(int a) { return (a <= 0) ? 1 : (getTen(a - 1) * 10); }
bool EQ(double a, double b) { return abs(a - b) < EPS; }
void fastStream() {
  cin.tie(0);
  std::ios_base::sync_with_stdio(0);
}
vector<string> split(string str, char del) {
  vector<string> res;
  for (int i = 0, s = 0; i < SIZE(str); i++) {
    if (str[i] == del) {
      if (i - s != 0)
        res.push_back(str.substr(s, i - s));
      s = i + 1;
    } else if (i == SIZE(str) - 1) {
      res.push_back(str.substr(s));
    }
  }
  return res;
}

int N;
double sy, sx, sz;
double gy, gx, gz;
double px[101][2];
double py[101][2];
double pz[101][2];
double d[101][101];

// 線分と点の間の距離を計算(3次元)
double calcDist(double x0, double y0, double z0, double x1, double y1,
                double z1, double px, double py, double pz) {
  double res = 0;
  double dy = y1 - y0;
  double dz = z1 - z0;
  double dx = x1 - x0;
  double a = dx * dx + dy * dy + dz * dz;
  double b = dx * x0 + dy * y0 + dz * z0;
  double c = (dx * px + dy * py + dz * pz);
  double t = 0;
  if (!EQ(a, 0)) {
    t = (c - b) / a;
    if (t < 0)
      t = 0;
    else if (t > 1)
      t = 1;
  }
  double ox = x0 + dx * t;
  double oy = y0 + dy * t;
  double oz = z0 + dz * t;
  res = sqrt((ox - px) * (ox - px) + (oy - py) * (oy - py) +
             (oz - pz) * (oz - pz));
  return res;
}

int main() {

  while (cin >> N && N) {
    cin >> sx >> sy >> sz >> gx >> gy >> gz;
    for (int i = 0; i < N; i++)
      for (int j = 0; j < 2; j++)
        cin >> px[i][j] >> py[i][j] >> pz[i][j];
    // すべての線分間の距離を計算
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        // 3分探索を用いて,2つの線分の間の距離を計算
        // どちらの線分に対して計算するかで場合分け
        d[i][j] = 1e+15;
        for (int k = 0; k < 2; k++) {
          int ary[2] = {i, j};
          double dx = px[i][1] - px[i][0];
          double dy = py[i][1] - py[i][0];
          double dz = pz[i][1] - pz[i][0];
          int cnt = 500;
          double ub = 1.0;
          double lb = 0;
          while (cnt--) {
            double mid1 = (ub - lb) / 3 + lb;
            double mid2 = (ub - lb) / 3 * 2 + lb;
            double len1 = calcDist(
                px[ary[k]][0], py[ary[k]][0], pz[ary[k]][0], px[ary[k]][1],
                py[ary[k]][1], pz[ary[k]][1], px[ary[k ^ 1]][0] + dx * mid1,
                py[ary[k ^ 1]][0] + dy * mid1, pz[ary[k ^ 1]][0] + dz * mid1);
            double len2 = calcDist(
                px[ary[k]][0], py[ary[k]][0], pz[ary[k]][0], px[ary[k]][1],
                py[ary[k]][1], pz[ary[k]][1], px[ary[k ^ 1]][0] + dx * mid2,
                py[ary[k ^ 1]][0] + dy * mid2, pz[ary[k ^ 1]][0] + dz * mid2);
            if (len1 < len2)
              ub = mid2;
            else
              lb = mid1;
          }
          double mid1 = ub;
          double len = calcDist(
              px[ary[k]][0], py[ary[k]][0], pz[ary[k]][0], px[ary[k]][1],
              py[ary[k]][1], pz[ary[k]][1], px[ary[k ^ 1]][0] + dx * mid1,
              py[ary[k ^ 1]][0] + dy * mid1, pz[ary[k ^ 1]][0] + dz * mid1);
          d[i][j] = min(d[i][j], len);
        }
      }
    }
    for (int k = 0; k < N; k++)
      for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
          d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    double res = 1e+15;
    // sy,sx,szとgx,gy,gzの２点がどのノード上に乗っているか調べる
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        double dist = calcDist(px[i][0], py[i][0], pz[i][0], px[i][1], py[i][1],
                               pz[i][1], sx, sy, sz);
        dist += calcDist(px[i][0], py[i][0], pz[i][0], px[i][1], py[i][1],
                         pz[i][1], gx, gy, gz);
        dist += d[i][j];
        res = min(res, dist);
      }
    }
    printf("%.10f\\n", res);
    // int spos=-1,gpos=-1;
    // for(int i=0;i<N;i++){
    //   if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],sx,sy,sz)))spos=i;
    //   if(EQ(0,calcDist(px[i][0],py[i][0],pz[i][0],px[i][1],py[i][1],pz[i][1],gx,gy,gz)))gpos=i;
    // }
    // cout<<calcDist(px[0][0],py[0][0],pz[0][0],px[0][1],py[0][1],pz[0][1],sx,sy,sz)<<endl;
    // cout<<spos<<" "<<gpos<<endl;
    // printf("%.10f\\n",d[spos][gpos]);
  }

  return 0;
}