Rezolvare completă PbInfo #869 Acces2

Cerința

Se consideră o clădire de formă dreptunghiulară, împărțită în n*m camere, dispuse sub forma unei matrice cu n linii și m coloane. Dintr-o cameră se poate trece în oricare dintre cele 4 camere vecine pe linie sau pe coloană. Unele camere sunt închise, și în ele nu se poate intra deloc. Trecerea dintr-o cameră în altă cameră durează un minut.

Camerele formează zone. O zonă este alcătuită dintr-un număr maxim de camere cu proprietatea că oricum am alege două camere din zonă se poate ajunge dintr-o cameră în alta trecând doar prin camere libere.

În anumite camere se află echipe de pompieri. Fiecare echipă deservește zona din care face parte camera echipei.

S-a constatat că așezarea echipelor în camere nu este tocmai corectă. Mai precis, există zone care nu sunt deservite de nicio echipă de pompieri. Pentru corectarea acestei probleme există două operații posibile:

  • mutarea unor echipe din camera curentă în altă cameră – operație care costă 1 leu
  • crearea unor echipe noi și plasare lor în camere – operație care costă 2 lei

Să se determine costul total minim al operațiilor necesare, astfel încât fiecare zonă din clădire să fie deservită de cel puțin o echipă de pompieri.

Date de intrare

Fișierul de intrare acces2.in conține pe prima linie numerele n m; următoarele n linii conțin câte m caractere, care pot fi:

  • - – reprezintă o cameră liberă
  • # – reprezintă o cameră închisă
  • P – reprezintă o cameră în care se găsește o echipă de pompieri

Date de ieșire

Fișierul de ieșire acces2.out va conține pe prima linie costul total minim.

Restricții și precizări

  • 1 ≤ n,m ≤ 1000

Exemplu

acces2.in

4 6
P-#-#P
--###-
##P-P#
--#--#

acces2.out

3

Explicație

În clădire sunt 5 zone: una este deservită de 2 echipe, două sunt deservite de câte o echipă și două nu sunt deservite deloc. Costul minim 3 se obține prin mutarea unei echipe (cost 1) și crearea unei echipe noi (cost 2).

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema Acces2:

#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;

ifstream fin("acces2.in");
ofstream fout("acces2.out");

int n , m;
short a[1001][1001];
int  x[1000001], y[1000001];
char P[1001][1001];
int nrechipe;

const int dx[] = {0 , 0 , 1 , -1}, 
          dy[] = {1 , -1 , 0 , 0};

void fill(int istart , int jstart , int nrz)
{
    //parcurgem zona curenta si determinam cate echipe sunt in ea
    int st = 1 , dr = 1;
    a[istart][jstart] = nrz;
    x[1] = istart, y[1] = jstart;
    nrechipe = 0;
    while(st <= dr)
    {
        int i = x[st], j = y[st];
        for(int k = 0 ; k < 4 ; k ++)
        {
            int ii = i + dx[k], jj = j + dy[k];
            if( ii > 0 && ii <= n && jj > 0 && jj <= m && P[ii][jj] != '#' && a[ii][jj] == 0)
            {
                dr ++;
                x[dr] = ii, y[dr] = jj;
                a[ii][jj] = nrz;
            }
        }
        if(P[i][j] == 'P')
            nrechipe ++;
        st ++;
    }
}

int main(){
    fin >> n >> m;
    for(int i = 1 ; i <= n ; i ++)
        for(int j = 1 ; j <= m ; j ++)
            fin >> P[i][j];
    fin.close();
    
    int nrzone = 0 , echipe_in_plus = 0;
    int nrz = 0;
    for(int i = 1 ; i <= n ; i ++)
        for(int j = 1 ; j <= m ; j ++)
            if(a[i][j] == 0 && P[i][j] != '#')
            {
                nrz ++;
                fill(i, j, nrz);
                if(nrechipe == 0)
                {
                    nrzone ++;
                }
                else
                    echipe_in_plus += nrechipe - 1;
            }
    
    if(echipe_in_plus >= nrzone)
        fout << nrzone;
    else
        fout << echipe_in_plus + 2 * (nrzone - echipe_in_plus);
    fout.close();
    return 0;
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #869 Acces2

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #869 Acces2 de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!