제출 #1344399

#제출 시각아이디문제언어결과실행 시간메모리
1344399s3narasiAstronomer (BOI23_astronomer)C++20
0 / 100
94 ms468 KiB
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <random>

using namespace std;

typedef long double ld;

struct Point {
    ld x, y;
};

int N, K;
ld S, T;
vector<Point> P;

// O(N) cost evaluation using nth_element
ld get_cost(ld cx, ld cy) {
    static vector<ld> dists;
    dists.resize(N);
    for (int i = 0; i < N; ++i) {
        ld dx = P[i].x - cx;
        ld dy = P[i].y - cy;
        dists[i] = sqrt(dx * dx + dy * dy);
    }
    nth_element(dists.begin(), dists.begin() + K - 1, dists.end());
    ld r = dists[K - 1];
    ld d = sqrt(cx * cx + cy * cy);
    return (T * r) + (S * d);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    if (!(cin >> N >> K >> S >> T)) return 0;
    P.resize(N);
    ld startX = 0, startY = 0;
    for (int i = 0; i < N; ++i) {
        cin >> P[i].x >> P[i].y;
        startX += P[i].x;
        startY += P[i].y;
    }
    startX /= N; startY /= N;

    // Simulated Annealing
    ld curX = startX, curY = startY;
    ld cur_cost = get_cost(curX, curY);
    ld min_cost = cur_cost;

    // Start with a large temperature to cover the coordinate range (10^9)
    ld temp = 1e9; 
    mt19937 rng(1337);
    uniform_real_distribution<ld> dist_unit(-1.0, 1.0);

    // This loop runs enough times to converge but stays within 1.5s
    for (int i = 0; i < 100000; ++i) {
        ld nextX = curX + dist_unit(rng) * temp;
        ld nextY = curY + dist_unit(rng) * temp;
        
        ld next_cost = get_cost(nextX, nextY);
        
        // Acceptance probability
        if (next_cost < cur_cost) {
            cur_cost = next_cost;
            curX = nextX;
            curY = nextY;
        } else {
            // Occasionally accept worse moves to jump out of local minima
            ld p = exp((cur_cost - next_cost) / temp);
            if (uniform_real_distribution<ld>(0, 1)(rng) < p) {
                cur_cost = next_cost;
                curX = nextX;
                curY = nextY;
            }
        }
        min_cost = min(min_cost, cur_cost);
        temp *= 0.9999; // Cool down slowly
    }

    // Final polish: small-scale hill climbing
    ld step = 100.0;
    for (int i = 0; i < 50; ++i) {
        bool improved = false;
        for (int d = 0; d < 8; ++d) {
            ld ang = d * M_PI / 4.0;
            ld nx = curX + cos(ang) * step;
            ld ny = curY + sin(ang) * step;
            ld nc = get_cost(nx, ny);
            if (nc < cur_cost) {
                cur_cost = nc;
                curX = nx;
                curY = ny;
                improved = true;
            }
        }
        if (!improved) step /= 2.0;
        min_cost = min(min_cost, cur_cost);
    }

    cout << fixed << setprecision(10) << min_cost << endl;

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...