Cod sursa(job #3357154)

Utilizator parus_majorParus Major parus_major Data 6 iunie 2026 17:51:53
Problema Barman Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.83 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

struct Pahar {
    int valoare;
    int id_initial;
};

// Sortare stabila: daca valorile sunt egale, pastram ordinea initiala relativă
bool comparaPahare(const Pahar& a, const Pahar& b) {
    if (a.valoare == b.valoare)
        return a.id_initial < b.id_initial;
    return a.valoare < b.valoare;
}

// Functie pentru calculul distantei minime pe un cerc de dimensiune N
int distantaCirculara(int i, int j, int N) {
    int dist_directa = abs(i - j);
    return min(dist_directa, N - dist_directa);
}

int main() {
    ifstream fin("barman.in");
    ofstream fout("barman.out");

    int N;
    if (!(fin >> N)) return 0;

    vector<Pahar> v(N);
    vector<Pahar> sortat(N);

    for (int i = 0; i < N; ++i) {
        fin >> v[i].valoare;
        v[i].id_initial = i;
        sortat[i] = v[i];
    }

    // Sortam paharele pentru a stabili configuratia de baza sortata
    sort(sortat.begin(), sortat.end(), comparaPahare);

    long long min_timp_total = -1;

    // Testam toate cele N configuratii finale (rotatii circulare)
    for (int start = 0; start < N; ++start) {
        vector<int> dest(N);

        // Mapam fiecare pahar initial la noua lui pozitie in rotatia curenta
        for (int i = 0; i < N; ++i) {
            int poz_tinta = (start + i) % N;
            int id_orig = sortat[i].id_initial;
            dest[id_orig] = poz_tinta;
        }

        vector<bool> vizitat(N, false);
        long long timp_curent = 0;

        for (int i = 0; i < N; ++i) {
            if (!vizitat[i]) {
                int nod = i;
                long long lungime_ciclu = 0;
                long long cost_deplasari_ciclu = 0;

                // Identificam si procesam ciclul de permutare
                while (!vizitat[nod]) {
                    vizitat[nod] = true;
                    int urmatorul = dest[nod];

                    if (nod != urmatorul) {
                        lungime_ciclu++;
                        // CORECTIE: Folosim distanta circulara minima
                        cost_deplasari_ciclu += distantaCirculara(nod, urmatorul, N);
                    }

                    nod = urmatorul;
                }

                if (lungime_ciclu > 0) {
                    // Costul unui ciclu: 
                    // 20 secunde per pahar (10s ridicat + 10s pus jos) + distanta parcursa cu el pe tava
                    timp_curent += (20 * lungime_ciclu) + cost_deplasari_ciclu;
                }
            }
        }

        if (min_timp_total == -1 || timp_curent < min_timp_total) {
            min_timp_total = timp_curent;
        }
    }

    fout << min_timp_total << "\n";

    fin.close();
    fout.close();
    return 0;
}