Cod sursa(job #3357163)

Utilizator parus_majorParus Major parus_major Data 6 iunie 2026 18:14:40
Problema Ferma Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.42 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

const long long INF = 1e18;

// Functie care calculeaza dinamica liniara standard pe un vector primit ca parametru
long long rezolva_liniar(const vector<long long>& v, int n, int k) {
    vector<long long> dp_prev0(k + 1, -INF);
    vector<long long> dp_prev1(k + 1, -INF);
    dp_prev0[0] = 0;

    for (int i = 0; i < n; ++i) {
        vector<long long> dp_curr0(k + 1, -INF);
        vector<long long> dp_curr1(k + 1, -INF);
        for (int j = 0; j <= k; ++j) {
            // Nu luam elementul curent
            if (dp_prev0[j] != -INF) dp_curr0[j] = max(dp_curr0[j], dp_prev0[j]);
            if (dp_prev1[j] != -INF) dp_curr0[j] = max(dp_curr0[j], dp_prev1[j]);

            // Luam elementul curent (incepem o secventa noua)
            if (j > 0) {
                if (dp_prev0[j - 1] != -INF) dp_curr1[j] = max(dp_curr1[j], dp_prev0[j - 1] + v[i]);
                if (dp_prev1[j - 1] != -INF) dp_curr1[j] = max(dp_curr1[j], dp_prev1[j - 1] + v[i]);
            }
            // Continuam o secventa existenta
            if (dp_prev1[j] != -INF) dp_curr1[j] = max(dp_curr1[j], dp_prev1[j] + v[i]);
        }
        dp_prev0 = move(dp_curr0);
        dp_prev1 = move(dp_curr1);
    }

    long long maxim = 0;
    for (int j = 0; j <= k; ++j) {
        maxim = max({ maxim, dp_prev0[j], dp_prev1[j] });
    }
    return maxim;
}

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

    int n, k;
    if (!(fin >> n >> k)) {
        fout << 0 << "\n";
        return 0;
    }

    vector<long long> v(n);
    int idx_minim = 0;
    long long val_minima = INF;

    for (int i = 0; i < n; ++i) {
        fin >> v[i];
        if (v[i] < val_minima) {
            val_minima = v[i];
            idx_minim = i;
        }
    }

    // Rulam cazul liniar direct asa cum este el primit
    long long ans = rezolva_liniar(v, n, k);

    // Reasamblam vectorul circular taindu-l dupa elementul minim.
    // Elementul minim are cele mai mari sanse sa fie lasat pe dinafara (sa fie spatiu intre secvente).
    vector<long long> v_circular;
    for (int i = 0; i < n; ++i) {
        v_circular.push_back(v[(idx_minim + 1 + i) % n]);
    }

    ans = max(ans, rezolva_liniar(v_circular, n, k));

    fout << ans << "\n";

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