QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#116796#4886. Best Sunhos_lyricWA 94ms7796kbC++147.1kb2023-06-30 06:59:252023-06-30 06:59:28

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-06-30 06:59:28]
  • 评测
  • 测评结果:WA
  • 用时:94ms
  • 内存:7796kb
  • [2023-06-30 06:59:25]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }


int sig(Int r) { return (r < 0) ? -1 : (r > 0) ? +1 : 0; }
struct Pt {
  Int x, y;
  Pt() : x(0), y(0) {}
  Pt(Int x_, Int y_) : x(x_), y(y_) {}
  Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
  Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
  Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
  Pt operator+() const { return Pt(+x, +y); }
  Pt operator-() const { return Pt(-x, -y); }
  Pt operator*(const Int &k) const { return Pt(x * k, y * k); }
  Pt operator/(const Int &k) const { return Pt(x / k, y / k); }
  friend Pt operator*(const Int &k, const Pt &a) { return Pt(k * a.x, k * a.y); }
  Pt &operator+=(const Pt &a) { x += a.x; y += a.y; return *this; }
  Pt &operator-=(const Pt &a) { x -= a.x; y -= a.y; return *this; }
  Pt &operator*=(const Pt &a) { return *this = *this * a; }
  Pt &operator*=(const Int &k) { x *= k; y *= k; return *this; }
  Int abs2() const { return x * x + y * y; }
  Int dot(const Pt &a) const { return x * a.x + y * a.y; }
  Int det(const Pt &a) const { return x * a.y - y * a.x; }
  bool operator==(const Pt &a) const { return (x == a.x && y == a.y); }
  bool operator<(const Pt &a) const { return (x < a.x || (x == a.x && y < a.y)); }
  friend ostream &operator<<(ostream &os, const Pt &a) { os << "(" << a.x << ", " << a.y << ")"; return os; }
};
Int tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }

// (-(1/2)PI, (3/2)PI]
int cmpArg(const Pt &a, const Pt &b) {
  const int sa = (a.x > 0) ? 0 : (a.x < 0) ? 2 : (a.y > 0) ? 1 : 3;
  const int sb = (b.x > 0) ? 0 : (b.x < 0) ? 2 : (b.y > 0) ? 1 : 3;
  return (sa < sb) ? -1 : (sa > sb) ? +1 : sig(b.det(a));
}


unsigned xrand() {
  static unsigned x = 314159265, y = 358979323, z = 846264338, w = 327950288;
  unsigned t = x ^ x << 11; x = y; y = z; z = w; return w = w ^ w >> 19 ^ t ^ t >> 8;
}


using Double = double;
constexpr Double INF = 1e+20;

int N;
vector<Pt> P;

Double D[310][310];
char S[310][310][310];

// inside triangle 0, i, j
int cnt[310][310];

// inside triangle i, j, k
int enclose(int i, int j, int k) {
  int ret = 0;
  ret += cnt[i][j];
  ret += cnt[j][k];
  ret += cnt[k][i];
  ret -= (S[0][j][i] + S[j][k][i] + S[k][0][i]) / 3;
  ret -= (S[0][k][j] + S[k][i][j] + S[i][0][j]) / 3;
  ret -= (S[0][i][k] + S[i][j][k] + S[j][0][k]) / 3;
#ifdef LOCAL
int brt=0;
for(int l=0;l<N;++l)brt+=abs((S[i][j][l]+S[j][k][l]+S[k][i][l])/3);
if(brt!=ret)cerr<<P[i]<<" "<<P[j]<<" "<<P[k]<<": "<<brt<<" "<<ret<<endl;
assert(brt==ret);
#endif
  return ret;
}

Double cost[310][310];

using Dir = pair<Pt, pair<int, pair<int, int>>>;
vector<Dir> dirs;

// s: min (x, y)
// area - ratio * length >= 0
bool check(int src, Double ratio) {
  vector<Double> dp(N, -INF);
  Double mx = -INF;
  dp[src] = 0.0;
  for (const auto &dir : dirs) {
    const int i = dir.second.second.first;
    const int j = dir.second.second.second;
    if (dir.second.first == 0) {
      if (S[src][i][j] >= 0 && enclose(src, i, j) == 0) {
        chmax((src == j) ? mx : dp[j], dp[i] + tri(P[src], P[i], P[j]) / 2.0 - ratio * cost[i][j]);
      }
    } else {
      dp[i] -= ratio * D[i][j];
    }
  }
  return (mx >= 0.0);
}

int main() {
  for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
    scanf("%d", &N);
    P.resize(N);
    for (int i = 0; i < N; ++i) {
      scanf("%lld%lld", &P[i].x, &P[i].y);
    }
    sort(P.begin(), P.end());
    
    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {
      D[i][j] = sqrt((Double)(P[j] - P[i]).abs2());
    }
    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) for (int k = 0; k < N; ++k) {
      S[i][j][k] = sig(tri(P[i], P[j], P[k]));
    }
    
    for (int i = 0; i < N; ++i) {
      fill(cnt[i], cnt[i] + N, 0);
    }
    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if (S[0][i][j] > 0) {
      for (int k = 0; k < N; ++k) {
        cnt[i][j] += (S[0][i][k] + S[i][j][k] + S[j][0][k]) / 3;
      }
      cnt[j][i] = -cnt[i][j];
    }
// if(N<=3)for(int i=0;i<N;++i)for(int j=0;j<N;++j)for(int k=0;k<N;++k)cerr<<i<<" "<<j<<" "<<k<<": "<<enclose(i,j,k)<<endl;
    
    /*
      cost of j at corner i:
        - come in [arg(P[j] - P[i]) - PI/2, arg(P[j] - P[i]) + PI/2]
        - go   in [arg(P[j] - P[i]) + PI/2, arg(P[j] - P[i]) - PI/2]
      
      for src != i
      impose when: come <= arg(P[j] - P[i]) + PI/2 < go
      (ignore non-convex turning)
      
      remaining cost: projected on the segment [i, j)
    */
    // projected on the segment
    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {
      cost[i][j] = D[i][j];
      for (int k = 0; k < N; ++k) {
        if (S[i][j][k] < 0 &&
            (P[j] - P[i]).dot(P[k] - P[i]) >= 0 &&
            (P[i] - P[j]).dot(P[k] - P[j]) >  0) {
          cost[i][j] += min(D[i][k], D[j][k]);
        }
      }
    }
    
    dirs.clear();
    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) if (i != j) {
      dirs.emplace_back(P[j] - P[i], make_pair(0, make_pair(i, j)));
      dirs.emplace_back((P[j] - P[i]) * Pt(0, 1), make_pair(1, make_pair(i, j)));
    }
    sort(dirs.begin(), dirs.end(), [&](const Dir &dir0, const Dir &dir1) -> bool {
      const int s = cmpArg(dir0.first, dir1.first);
      return (s ? (s < 0) : (dir0.second < dir1.second));
    });
// cerr<<"dirs = "<<dirs<<endl;
    
    vector<int> ss(N);
    for (int i = 0; i < N; ++i) {
      swap(ss[xrand() % (i + 1)], ss[i] = i);
    }
    Double lo = 0.0;
    for (const int s : ss) {
      if (check(s, lo)) {
        Double hi = 1e+9;
        for (int iter = 0; iter < 60; ++iter) {
          const Double mid = (lo + hi) / 2.0;
          (check(s, mid) ? lo : hi) = mid;
        }
      }
    }
    printf("%.12f\n", lo);
  }
#ifndef LOCAL
  break;
#endif
  }
  return 0;
}

详细

Test #1:

score: 100
Accepted
time: 2ms
memory: 7796kb

input:

4
3
-1 -1
1 -1
0 1
4
0 0
10 0
0 10
8 1
5
2 0
-2 0
1 1
-1 1
0 3
8
4 4
-4 4
4 -4
-4 -4
5 6
-6 5
-5 -6
6 -5

output:

0.309016994285
1.236861427514
0.271137541238
1.563100209420

result:

ok 4 numbers

Test #2:

score: 0
Accepted
time: 82ms
memory: 3816kb

input:

10000
3
702262 828158
-350821 -420883
-466450 13507
3
28647 -193498
126436 -864937
-287798 738936
3
270358 -269567
745815 -485408
834083 677952
3
-2036 -403634
742978 -263774
975937 -609237
3
584248 -472620
482016 -356760
284902 903881
3
-292004 504925
-935756 373793
-781101 -434659
3
-858513 684433...

output:

85789.087398353484
18268.519361671824
102489.988390261860
66685.754428079395
18674.657937413525
106468.965131971927
14427.024651070264
29966.245302542360
143547.751083586772
13097.175688125615
162410.168316980125
72070.932417874283
29369.992627886582
52867.294431100876
90314.308346756327
99775.92719...

result:

ok 10000 numbers

Test #3:

score: 0
Accepted
time: 82ms
memory: 3816kb

input:

10000
3
2 2
2 -2
-5 -5
3
-3 5
5 -4
2 -2
3
-4 1
2 -2
-4 4
3
1 -4
2 1
-4 1
3
2 1
-1 1
-3 3
3
4 5
3 -1
-3 -3
3
1 5
5 0
5 -1
3
2 -3
-5 -3
5 3
3
-4 4
0 -5
5 4
3
2 -3
5 0
2 -5
3
-2 -3
5 -3
5 4
3
-1 4
4 4
4 3
3
5 3
-1 4
2 -1
3
2 -3
4 3
-4 3
3
0 4
-2 -2
-1 -3
3
-2 0
-4 -2
4 2
3
-3 -1
3 1
1 -3
3
2 -5
2 3
-4 ...

output:

0.650700700787
0.226809069789
0.494682565744
0.825532630970
0.267532474472
0.737928456188
0.136852946510
0.827745795517
1.389628120040
0.248476165858
1.025126265125
0.225245121166
0.798168850458
1.052177633215
0.270090756184
0.221028003192
0.654929147373
1.065792545364
0.120736187541
0.172721212333
...

result:

ok 10000 numbers

Test #4:

score: -100
Wrong Answer
time: 94ms
memory: 5796kb

input:

5625
4
-405394 -381883
602267 -335687
-620806 984110
271283 531233
4
196903 -993060
290851 358123
-890076 -717709
-681138 209884
4
-849589 607722
-21517 -586295
208561 -220953
924518 622983
4
-832186 456270
289934 43656
636006 339718
188963 113907
4
-305762 -872205
-520125 368722
-774548 984204
4245...

output:

232625.004274430394
268175.826985963213
159589.323630517232
60440.753042598313
160077.128456144186
63201.990748626078
167697.663406134292
129470.013284315559
126903.854072810122
120109.808780404855
131692.311227904691
100421.055016211729
148490.274817902071
68842.242309822439
241376.191116128699
303...

result:

wrong answer 5th numbers differ - expected: '133893.1234364', found: '160077.1284561', error = '0.1955590'