2959 - minecraft

De la Universitas MediaWiki

Cerința

Tommy a descoperit bine-cunoscutul joc Minecraft, joc care este axat pe creativitate și construcție, permițând jucătorilor să construiască, folosind o multitudine de cuburi texturate, o lume tridimensională. Harta lumii lui Tommy este o suprafață pătrată, pe care sunt desenate pătrate egale, alăturate, ce pot fi albastre sau verzi. Fiecare pătrat albastru corespunde unui cub albastru și fiecare pătrat verde corespunde unui cub verde. Sursele de apă sunt reprezentate de pătrate de culoare albastră. Fiecare pătrat verde are atașat un cost, reprezentat de lungimea celui mai scurt drum până la o sursă de apă. Două pătrate alăturate aparțin aceluiași drum dacă au o latură comună. Drumul ajunge la o sursă de apă, dacă, ultimul pătrat de pe drum are o latură comună cu pătratul corespunzător sursei de apă. Lungimea drumului este reprezentată de numărul de pătrate care formează drumul. Costul unei suprafețe este reprezentat de suma costurilor pătratelor care formează suprafața.

Pe harta din figura 3 sunt reprezentate costurile pătratelor verzi. Pentru a putea supraviețui în această lume, Tommy trebuie să-și construiască o casă, având două posibilități:

a) Modul Supraviețuire: construiește o casă pe o zonă dreptunghiulară ce conține cel puțin o sursă de apă;
b) Modul Creativ: construiește o casă pe o suprafață pătrată de arie maximă, ce nu conține surse de apă dar este învecinată cu cel puțin o sursă de apă. Dacă sunt mai multe astfel de suprafețe, alege una ce are cost minim.

Date de intrare

Cunoscând harta ce corespunde lumii lui Tommy, să se determine:

  • numărul zonelor dreptunghiulare pe care poate construi casa în modul Supraviețuire;
  • aria suprafeței pe care-și construiește casa și costul acesteia în modul Creativ.

Date de ieșire

Fișierul standard de ieșire are o singură linie ce conține:

  • dacă C = 1, un singur număr ce reprezintă numărul zonelor dreptunghiulare pe care poate construi casa în modul Supraviețuire;
  • dacă C = 2, două numere naturale separate prin spațiu, ce reprezintă aria suprafeței pe care construiește casa și costul acesteia, în modul Creativ.

Restricții și precizări

  • 2 ≤ N ≤ 1000
  • Harta conține cel puțin o sursă de apă și cel puțin o zonă verde.

Exemplu 1

Intrare

1
3
VVA
AVV
VVV

Iesire

19

Rezolvare

def numara_zona_supravietuire(harta, N):
    def dfs(i, j):
        if i < 0 or i >= N or j < 0 or j >= N or harta[i][j] == 'A' or vizitat[i][j]:
            return
        vizitat[i][j] = True
        dfs(i + 1, j)
        dfs(i - 1, j)
        dfs(i, j + 1)
        dfs(i, j - 1)

    vizitat = [[False] * N for _ in range(N)]
    zone_supravietuire = 0

    for i in range(N):
        for j in range(N):
            if harta[i][j] == 'V' and not vizitat[i][j]:
                zone_supravietuire += 1
                dfs(i, j)

    return zone_supravietuire


def zona_maxima_creativ(harta, N):
    def max_histogram_area(histogram):
        stack = []
        max_area = 0
        index = 0

        while index < len(histogram):
            if not stack or histogram[stack[-1]] <= histogram[index]:
                stack.append(index)
                index += 1
            else:
                top_of_stack = stack.pop()
                area = (histogram[top_of_stack] *
                        ((index - stack[-1] - 1) if stack else index))
                max_area = max(max_area, area)

        while stack:
            top_of_stack = stack.pop()
            area = (histogram[top_of_stack] *
                    ((index - stack[-1] - 1) if stack else index))
            max_area = max(max_area, area)

        return max_area

    max_area = 0
    dp = [0] * N

    for i in range(N):
        for j in range(N):
            if harta[i][j] == 'V':
                dp[j] += 1
            else:
                dp[j] = 0
        max_area = max(max_area, max_histogram_area(dp))

    return max_area


def numara_toate_zonele(harta, N):
    zone_supravietuire = 0
    for top in range(N):
        for left in range(N):
            for bottom in range(top, N):
                for right in range(left, N):
                    found_water = False
                    for i in range(top, bottom + 1):
                        for j in range(left, right + 1):
                            if harta[i][j] == 'A':
                                found_water = True
                    if found_water:
                        zone_supravietuire += 1
    return zone_supravietuire


def main():
    K = int(input().strip())
    N = int(input().strip())

    assert 2 <= N <= 1000, "N trebuie sa fie intre 2 si 1000"

    harta = []
    for _ in range(N):
        row = list(input().strip())
        assert len(row) == N, "Fiecare rând trebuie să aibă exact N caractere"
        assert all(c in {'A', 'V'} for c in row), "Harta poate contine doar caracterele 'A' si 'V'"
        harta.append(row)

    if K == 1:
        zone_supravietuire = numara_toate_zonele(harta, N)
        print(f"{zone_supravietuire}")
    elif K == 2:
        zona_creativ = zona_maxima_creativ(harta, N)
        print(f"{zona_creativ}")
    else:
        print("Valoare K invalidă")


if __name__ == "__main__":
    main()

if __name__ == "__main__":
    main()