Cod sursa(job #3331008)

Utilizator maxtraAlex Deonise maxtra Data 23 decembrie 2025 17:36:52
Problema Aprindere Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.39 kb
/*
enunt:
ai N camere in linie: 0, 1, .., N-1, fiecare are un bec (0 - stins, 1 - aprins)
exista M intrerupatoare (cel putin 1 in fiecare camera). un intrerupator aflat in camera C:
- intotdeauna schimba starea becului din camera C;
- poate schimba si becuri din camere cu index mai mare decat C;
- actionarea lui costa T timp;

schimbarea starii: toggle intre 0 si 1

scop: sa ajungi ca in toate camerele sa fie becul aprins (1) cu timp total minim

solutie:
de ce nu merge un algoritm de la stanga-dreapta
pentru o camera i:
- intrerupatoarele din camere mai mari (> i) NU au voie sa ii modifice becul (un intrerupator 
modifica becul din camera sa si eventual dupa ea)
- deci dupa ce ai trecut de i, nu mai poti modifica becul din i

asta face decizia ca la camera i sa fie fortata:
- daca atunci cand ajungi la i, becul este 0, trebuie doar sa apesi intrerupatorul din i ca sa l aprinzi
- daca e 1, nu l apesi (altfel l ai stinge si nu mai ai cum sa l reaprinzi mai tarziu)

prin urmare, solutia minima este practic deterministica: parcurgi camerele in ordine si apesi exact unde este nevoie
(Alg de tip Greedy)

algoritm:
citesti n si m
citesc starea initiala a becurilor in a[0..n-1]
citesti toate intrerupatoarele in vectorul v[], avand:
- poz = camera unde este intrerupatorul
- t = timpul de apasare
- nr = camera modificata
- c[] = lista camerelor modificate (include mereu poz)
parcurgerea intrerupatoarelor si pentru fiecare:
- daca in camera lui (a[poz]) becul este stins, apasa
- daca face toggle pentru toate camerele din lista c[]
- adauga timpul t in sum
scrie sum
*/
#include <bits/stdc++.h>
using namespace std;

// Pentru fiecare cameră putem avea cel mult un întrerupător.
struct SwitchInfo {
    bool exists = false;   // există întrerupător în camera asta?
    int t = 0;             // timpul de apăsare
    int nr = 0;            // câte camere modifică
    int c[105];            // lista camerelor modificate (nr <= 100)
};

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

    int n, m;
    fin >> n >> m;

    // a[i] = starea becului din camera i (0/1)
    int a[1001];
    for (int i = 0; i < n; i++) fin >> a[i];

    // sw[C] = întrerupătorul din camera C (dacă există)
    SwitchInfo sw[1001];

    for (int k = 0; k < m; k++) {
        int C, T, NRC;
        fin >> C >> T >> NRC;

        sw[C].exists = true;
        sw[C].t = T;
        sw[C].nr = NRC;

        for (int j = 0; j < NRC; j++) {
            fin >> sw[C].c[j];
        }
    }

    long long sum = 0;

    // Parcurgem camerele în ordine (0..N-1).
    // IMPORTANT: după ce trecem de i, nimic din dreapta nu mai poate modifica camera i.
    for (int i = 0; i < n; i++) {
        if (!sw[i].exists) {
            // În teste există mereu soluție, deci dacă i e 0 acum, înseamnă că a fost
            // aprinsă din întrerupătoare anterioare. (Sau era deja 1.)
            continue;
        }

        // Dacă becul din camera i este stins când ajungem aici, trebuie apăsat.
        if (a[i] == 0) {
            // Apăsăm întrerupătorul: toggle pe toate camerele din lista lui.
            for (int j = 0; j < sw[i].nr; j++) {
                int room = sw[i].c[j];
                a[room] ^= 1;  // toggle: 0->1, 1->0
            }
            sum += sw[i].t;
        }
        // Dacă a[i] e deja 1, nu apăsăm (altfel l-am stinge și nu îl mai putem repara).
    }

    fout << sum;
    return 0;
}