# PBinfo #869 – Acces2 – Rezolvare C++

Sursa: Codul lui Andrei
Limbaj: C++
Autor rezolvare: Darius

## Enunț

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).

## Cod sursă C++

```cpp
#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;
}
```

## Resurse

- [Pagina originală](https://codulluiandrei.ro/rezolvari/pbinfo/869)
- [Sursa C++](https://codulluiandrei.ro/rezolvari/pbinfo/869/cod.cpp)
- [Sursa pe GitHub](https://raw.githubusercontent.com/codulluiandrei/pbinfo/main/pbinfo-869/main.cpp)
- [Cursuri de informatică pentru BAC](https://codulluiandrei.ro/academia/info-curs/pachet-cpp/)
