Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions algorithmic/problems/301/chk.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#include "testlib.h"

#include <bits/stdc++.h>
using namespace std;

using u64 = uint64_t;

struct Pt {
long double x, y;
};

static inline long double cross(const Pt& a, const Pt& b, const Pt& c) {
// cross((b-a),(c-a))
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}

static inline long double distPointSegment(const Pt& p, const Pt& a, const Pt& b) {
long double abx = b.x - a.x, aby = b.y - a.y;
long double apx = p.x - a.x, apy = p.y - a.y;
long double ab2 = abx * abx + aby * aby;
long double t = 0.0L;
if (ab2 > 0) t = (apx * abx + apy * aby) / ab2;
if (t < 0) t = 0;
if (t > 1) t = 1;
long double cx = a.x + t * abx;
long double cy = a.y + t * aby;
long double dx = p.x - cx;
long double dy = p.y - cy;
return sqrtl(dx * dx + dy * dy);
}

struct XorShiftStar {
u64 x;
explicit XorShiftStar(u64 seed) : x(seed) {}
u64 nextU64() {
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
return x * 2685821657736338717ULL;
}
long double nextU01() {
// uniform in [0,1)
u64 v = nextU64();
return ldexpl((long double)v, -64);
}
};

static bool parseIntStrict(const string& s, long long& out) {
// Accept optional leading +/-, then digits; no spaces.
if (s.empty()) return false;
size_t i = 0;
if (s[0] == '+' || s[0] == '-') i = 1;
if (i == s.size()) return false;
for (; i < s.size(); i++) if (!isdigit((unsigned char)s[i])) return false;
try {
size_t pos = 0;
long long v = stoll(s, &pos, 10);
if (pos != s.size()) return false;
out = v;
return true;
} catch (...) {
return false;
}
}

int main(int argc, char** argv) {
registerTestlibCmd(argc, argv);

int n = inf.readInt();
int m = inf.readInt();
int K = inf.readInt();
int S = inf.readInt();
u64 seed = inf.readUnsignedLong();

vector<Pt> vtx(n);
for (int i = 0; i < n; i++) {
long long xi = inf.readLong();
long long yi = inf.readLong();
vtx[i].x = (long double)xi;
vtx[i].y = (long double)yi;
}

vector<pair<int,int>> cand(m);
for (int j = 0; j < m; j++) {
int a = inf.readInt();
int b = inf.readInt();
cand[j] = {a, b};
}

// --- Generate deterministic sample points (uniform in convex polygon via fan triangulation) ---
// Triangles: (0, i, i+1), i=1..n-2 => count = n-2
vector<long double> pref; pref.reserve(max(0, n - 2));
long double totalA = 0.0L;
for (int i = 1; i <= n - 2; i++) {
long double area2 = cross(vtx[0], vtx[i], vtx[i+1]); // positive for CCW convex
long double Ai = area2 / 2.0L;
totalA += Ai;
pref.push_back(totalA);
}

XorShiftStar rng(seed);
vector<Pt> samples;
samples.reserve(S);

for (int t = 0; t < S; t++) {
long double r = rng.nextU01() * totalA;
auto it = upper_bound(pref.begin(), pref.end(), r);
int idx = (int)(it - pref.begin()); // 0..n-3
int i = idx + 1; // triangle is (0,i,i+1)
const Pt& a = vtx[0];
const Pt& b = vtx[i];
const Pt& c = vtx[i+1];

long double u = rng.nextU01();
long double vv = rng.nextU01();
long double s = sqrtl(u);
long double alpha = 1.0L - s;
long double beta = s * (1.0L - vv);
long double gamma = s * vv;

Pt p;
p.x = alpha * a.x + beta * b.x + gamma * c.x;
p.y = alpha * a.y + beta * b.y + gamma * c.y;
samples.push_back(p);
}

auto computeOBJ = [&](const vector<int>& ids) -> long double {
// Prebuild segment endpoints
vector<pair<Pt,Pt>> segs;
segs.reserve(ids.size());
for (int id : ids) {
auto [u, w] = cand[id];
segs.push_back({vtx[u], vtx[w]});
}
long double sum = 0.0L;
for (const Pt& p : samples) {
long double best = numeric_limits<long double>::infinity();
for (auto& seg : segs) {
long double d = distPointSegment(p, seg.first, seg.second);
if (d < best) best = d;
}
sum += best;
}
return sum / (long double)S;
};

// --- Read participant output; treat any format/feasibility issue as infeasible (score 0) ---
bool feasible = true;
vector<int> you;
you.reserve(K);

for (int i = 0; i < K; i++) {
if (ouf.seekEof()) { feasible = false; break; }
string tok = ouf.readToken();
long long val;
if (!parseIntStrict(tok, val)) { feasible = false; break; }
if (val < 0 || val >= m) feasible = false;
you.push_back((int)val);
}
if (feasible && !ouf.seekEof()) feasible = false; // must be exactly K tokens

if (feasible) {
vector<int> tmp = you;
sort(tmp.begin(), tmp.end());
for (int i = 1; i < (int)tmp.size(); i++) {
if (tmp[i] == tmp[i-1]) { feasible = false; break; }
}
}

// Baseline: IDs 0..K-1
vector<int> base;
base.reserve(K);
for (int i = 0; i < K; i++) base.push_back(i);

long double B = computeOBJ(base);

if (!feasible) {
// Infeasible output => worst objective; return 0 score ratio.
quitp(0.0, "Infeasible output. Baseline OBJ=%.12Lf", B);
}

long double Y = computeOBJ(you);

// Scoring: simple baseline-relative improvement
// ratio = clamp((B - Y)/B, 0..1)
long double denom = max(B, 1e-30L);
long double ratioLD = (B - Y) / denom;
if (ratioLD < 0) ratioLD = 0;
if (ratioLD > 1) ratioLD = 1;

double ratio = (double)ratioLD;
quitp(ratio, "Ratio: %.9f BaselineOBJ=%.12Lf YourOBJ=%.12Lf", ratio, B, Y);
}
7 changes: 7 additions & 0 deletions algorithmic/problems/301/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
checker: chk.cc
memory: 256m
subtasks:
- n_cases: 10
score: 100
time: 2s
type: default
184 changes: 184 additions & 0 deletions algorithmic/problems/301/statement.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
```markdown
# Rope Network for Xiaotu (Optimization)

## Problem
Xiaotu is training for sprints inside a **convex polygon** playground with \(n\) vertices \((0 \ldots n-1)\) listed in counterclockwise order.

The organizer will install **exactly \(K\)** “safety ropes”. Each rope is a straight segment connecting two polygon vertices (an edge or a diagonal). Because the polygon is convex, every such segment lies fully inside the playground.

When Xiaotu is at a position \(p\) (uniformly random inside the polygon), he runs straight to the **nearest rope** (Euclidean distance to the segment). Your task is to choose which \(K\) ropes to install (from a given candidate list) to **minimize the expected running distance**.

This is an open-ended optimization task: many different valid outputs exist, and they get different scores.

---

## Input
```
n m K S seed
x0 y0
x1 y1
...
x(n-1) y(n-1)
a0 b0
a1 b1
...
a(m-1) b(m-1)
```

- \(n\): number of polygon vertices.
- \(m\): number of candidate ropes.
- \(K\): number of ropes you must select.
- \(S\): number of evaluation sample points used by the judge.
- `seed`: 64-bit unsigned integer used to deterministically generate the \(S\) sample points.

Vertices:
- Each of the next \(n\) lines gives integer coordinates \((x_i, y_i)\).

Candidates:
- Each of the next \(m\) lines gives two integers \((a_j, b_j)\) with \(0 \le a_j < b_j < n\), specifying a candidate rope between vertices \(a_j\) and \(b_j\).

### Guarantees
- The polygon is strictly convex.
- No three vertices are collinear.
- Vertices are given counterclockwise.
- \(1 \le K \le m\).

---

## Output
Output exactly \(K\) **distinct** integers:
```
id1 id2 ... idK
```
where each `id` is in \([0, m-1]\), identifying selected candidate ropes.

### Feasibility rules
A submission is **feasible** iff:
- Exactly \(K\) integers are printed.
- All are distinct.
- All are in \([0, m-1]\).

Infeasible outputs receive a score of `0` (see **Scoring**).

---

## Objective
Let the selected rope set be \(R\) (size \(K\)).

The judge deterministically generates \(S\) points \(p_0, \dots, p_{S-1}\) **uniformly at random in the polygon** (but using the fixed `seed`, so it is deterministic).

For each point \(p\), define its cost:
\[
d(p, R) = \min_{(u,v)\in R} \mathrm{dist}(p, \overline{uv})
\]
where \(\mathrm{dist}(p, \overline{uv})\) is the Euclidean distance from point \(p\) to the **segment** from vertex \(u\) to vertex \(v\).

For a feasible output, your objective value is the mean distance:
\[
\mathrm{OBJ} = \frac{1}{S}\sum_{t=0}^{S-1} d(p_t, R)
\]
You must **minimize** `OBJ`.

---

## Deterministic sampling (used by the judge)
Because the polygon is convex, the judge triangulates it as a fan from vertex 0:
\[
T_i = (0, i, i+1), \quad i=1 \ldots n-2
\]
Let \(A_i\) be the (positive) area of triangle \(T_i\), and \(A=\sum A_i\).

### PRNG
The judge uses this 64-bit xorshift* generator:

- State is `uint64 x`, initialized to `seed`.
- Each call:
- `x ^= x >> 12; x ^= x << 25; x ^= x >> 27;`
- return `x * 2685821657736338717ULL`.

To get a uniform real in \([0,1)\), the judge uses:
\[
U = \frac{\text{next\_uint64()}}{2^{64}}
\]

### Sampling one point
For each sample \(t\):
1. Draw \(r = U_1 \cdot A\). Choose the smallest \(i\) with \(\sum_{j=1}^{i} A_j > r\).
2. In triangle \((a,b,c) = (v_0, v_i, v_{i+1})\), draw \(u=U_2, v=U_3\), then set:
- \(s=\sqrt{u}\)
- \(\alpha = 1-s,\ \beta = s(1-v),\ \gamma = sv\)
- \(p = \alpha a + \beta b + \gamma c\)

This produces points uniform over the polygon.

---

## Scoring
This is a **minimization** problem.

For each test case, the judge computes:
- `OBJ_you`: your objective value.
- `OBJ_base`: the objective value of a deterministic internal reference solution computed from that test case.

### Per-test score
Let:
- \(B = \mathrm{OBJ\_base}\)
- \(Y = \mathrm{OBJ\_you}\)

If your output is infeasible, then `score_test = 0`.

Otherwise, the score for that test is:
\[
\mathrm{score\_test} = \mathrm{clamp}\left(\frac{B - Y}{\max(B, 10^{-30})},\ 0,\ 1\right)
\]

This means:
- matching the baseline gets score `0`
- improving on the baseline gives a score in `(0, 1]`
- doing worse than the baseline is clamped to `0`

### Final score
The checker emits one per-test ratio in `[0, 1]` for each hidden test case.
The final score is the sum of these per-test ratios, scaled to the total points configured for this problem.

---

## Constraints
- Time limit: 2 seconds
- Memory limit: 256 MB

Hidden tests satisfy:
- \(3 \le n \le 100{,}000\)
- \(1 \le m \le 200{,}000\)
- \(1 \le K \le 50\)
- \(5{,}000 \le S \le 50{,}000\)
- \(-10^9 \le x_i,y_i \le 10^9\)

---

## Example
### Sample input
```
5 7 2 5000 1234567
0 0
10 0
12 6
6 12
-2 7
0 1
1 2
2 3
3 4
0 2
1 3
0 3
```

### Sample output
```
4 5
```

### Explanation (high level)
You chose candidate ropes #4 \((0,2)\) and #5 \((1,3)\). The judge generates 5000 deterministic uniform sample points inside the polygon (using seed 1234567), computes for each point the distance to the nearer of these two segments, averages those distances to get `OBJ_you`, then compares that objective against the judge's deterministic reference objective to compute the normalized score.
```
Empty file.
7 changes: 7 additions & 0 deletions algorithmic/problems/301/testdata/1.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
3 3 1 5000 2696223999546879974
0 0
10 0
0 10
0 1
0 2
1 2
Empty file.
Loading
Loading