Submission #97887

#TimeUsernameProblemLanguageResultExecution timeMemory
97887Alexa2001Fences (JOI18_fences)C++17
100 / 100
524 ms3192 KiB
#include <bits/stdc++.h>
#define x real()
#define y imag()

using namespace std;

const int Nmax = 210;
const long double eps = 1e-6;

typedef complex<long double> point;

long double dist[Nmax][2][Nmax][2];
int S, N;
point a[Nmax], O, W;
point S1[10], S2[10];


int Pair(int k)
{
    if(k >= 2*N) return -1;
    return k^1;
}

long double distanta(point A, point B)
{
    return abs(A - B);
}

long double cross(point a, point b)
{
    return (conj(a) * b).y;
}

long double dot(point a, point b)
{
    return (conj(a) * b).x;
}

bool on_segm(point A, point B, point C) /// este A pe segmentul [BC]?
{
    return distanta(A, B) + distanta(A, C) - distanta(B, C) < eps;
}

point reflect(point A, point B, point C)
{
    A -= B; C -= B;
    return B + (conj(A / C)) * C;
}

point perp(point A, point B, point C) /// perpendiculara din A pe dreapta BC
{
    return (A + reflect(A, B, C)) / (long double) 2;
}

point intersect(point a, point b, point c, point d)
{
    b -= a; c -= a; d -= a;
    long double c1 = cross(c, b), c2 = cross(d, b);
    return a + (c1 * d - c2 * c) / (c1 - c2);
}

bool inters_segm(point a, point b, point c, point d)
{
    if(cross(c-a, b-a) == cross(d-a, b-a)) return 0; /// paralele
    point P = intersect(a, b, c, d);
    return on_segm(P, a, b) && on_segm(P, c, d);
}

bool pass(point a, point b)
{
    return inters_segm(a, b, O, W);
}

bool is_ok(point A, point B) /// trece dreapta AB prin interiorul patratului initial?
{
    int i;
    for(i=0; i<4; ++i)
        if(inters_segm(A, B, S1[i], S2[i])) return 0;
    return 1;
}

void add_edge(int s, int t, long double D, bool p)
{
    dist[s][0][t][p] = min(dist[s][0][t][p], D);
    dist[s][1][t][p^1] = min(dist[s][1][t][p^1], D);
    swap(s, t);
    dist[s][0][t][p] = min(dist[s][0][t][p], D);
    dist[s][1][t][p^1] = min(dist[s][1][t][p^1], D);
}

void find_edge(int s, int t)
{
    if(Pair(s) == t) /// puncte de pe acelasi segment
    {
        add_edge(s, t, 0, pass(a[s], a[t]));
        return;
    }

    if(is_ok(a[s], a[t]))
        add_edge(s, t, distanta(a[s], a[t]), pass(a[s], a[t]));

    int z = Pair(s);
    if(z != -1)
    {
        point P = perp(a[t], a[s], a[z]);
        if(on_segm(P, a[s], a[z]) && is_ok(a[t], P))
            add_edge(s, t, distanta(a[t], P), pass(a[t], P) ^ pass(P, a[s]));
    }

    swap(s, t);
    z = Pair(s);
    if(z != -1)
    {
        point P = perp(a[t], a[s], a[z]);
        if(on_segm(P, a[s], a[z]) && is_ok(a[t], P))
            add_edge(s, t, distanta(a[t], P), pass(a[t], P) ^ pass(P, a[s]));
    }
}

int main()
{
 //   freopen("input", "r", stdin);
    cin.sync_with_stdio(false);

    int i, n;
    cin >> N >> S;
    for(i=0; i<N; ++i)
    {
        long double X, Y;
        cin >> X >> Y;
        a[2*i] = {X, Y};
        cin >> X >> Y;
        a[2*i+1] = {X, Y};
    }

    n = 2*N;
    a[n++] = {-S, S};
    a[n++] = {S, S};
    a[n++] = {S, -S};
    a[n++] = {-S, -S};

    O = {0, 0}; W = {251, 257};

    S1[0] = S2[3] = a[2*N] + point(eps, -eps);
    S1[1] = S2[0] = a[2*N+1] + point(-eps, -eps);
    S1[2] = S2[1] = a[2*N+2] + point(-eps, +eps);
    S1[3] = S2[2] = a[2*N+3] + point(eps, +eps);



    int j, k, i2, j2, k2;

    for(i=0; i<n; ++i)
        for(i2=0; i2<2; ++i2)
        {
            for(j=0; j<n; ++j)
                for(j2=0; j2<2; ++j2)
                    dist[i][i2][j][j2] = 10 * S;
            dist[i][i2][i][i2] = 0;
        }

    for(i=0; i<n; ++i)
        for(j=i+1; j<n; ++j)
            find_edge(i, j);

    for(k=0; k<n; ++k)
        for(k2=0; k2<2; ++k2)
            for(i=0; i<n; ++i)
                for(i2=0; i2<2; ++i2)
                    for(j=0; j<n; ++j)
                        for(j2=0; j2<2; ++j2)
                            dist[i][i2][j][j2] = min(dist[i][i2][j][j2], dist[i][i2][k][k2] + dist[k][k2][j][j2]);

    long double ans = 10 * S;
    for(i=0; i<n; ++i)
    {
        ans = min(ans, dist[i][0][i][1]);
     //   assert(dist[i][0][i][1] == dist[i][1][i][0]);
    }

    cout << setprecision(10) << fixed;
    cout << ans << '\n';
    return 0;
}

Compilation message (stderr)

fences.cpp: In function 'int main()':
fences.cpp:137:15: warning: narrowing conversion of '- S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {-S, S};
               ^~
fences.cpp:137:20: warning: narrowing conversion of 'S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {-S, S};
                    ^
fences.cpp:138:19: warning: narrowing conversion of 'S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {S, S};
                   ^
fences.cpp:138:19: warning: narrowing conversion of 'S' from 'int' to 'long double' inside { } [-Wnarrowing]
fences.cpp:139:20: warning: narrowing conversion of 'S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {S, -S};
                    ^
fences.cpp:139:18: warning: narrowing conversion of '- S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {S, -S};
                  ^~
fences.cpp:140:15: warning: narrowing conversion of '- S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {-S, -S};
               ^~
fences.cpp:140:19: warning: narrowing conversion of '- S' from 'int' to 'long double' inside { } [-Wnarrowing]
     a[n++] = {-S, -S};
                   ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...