2959 - minecraft: Diferență între versiuni

De la Universitas MediaWiki
 
(Nu s-au afișat 2 versiuni intermediare efectuate de același utilizator)
Linia 1: Linia 1:
== Cerința ==
== Cerința ==
În lumea Minecraft, jucătorii își organizează inventarul folosind stive pentru a stoca diferite blocuri și obiecte. Ei pot adăuga blocuri la stivă sau pot scoate blocuri din stivă în funcție de nevoile lor de construcție. Sarcina ta este să implementezi un program care să simuleze aceste operațiuni asupra unei stive de blocuri.
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 -ș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ă;<br>
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 ==
== Date de intrare ==
Programul citește de la tastatură:
Cunoscând harta ce corespunde lumii lui Tommy, să se determine:


Un număr întreg n reprezentând numărul de operațiuni.
*numărul zonelor dreptunghiulare pe care poate construi casa în modul Supraviețuire;
O listă de n operațiuni, fiecare operațiune fiind de forma "PUSH X" (unde X este un tip de bloc) sau "POP".
*aria suprafeței pe care-și construiește casa și costul acesteia în modul Creativ.
== Date de ieșire ==
== Date de ieșire ==
Pe ecran se va afișa stiva rezultată după efectuarea tuturor operațiunilor. Dacă o operațiune "POP" este efectuată pe o stivă goală, se va afișa mesajul "Eroare: stivă goală".
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 ==
== Restricții și precizări ==
*1 &les; '''n''' &les; 100
*2 ≤ N ≤ 1000
* 'x' este întotdeauna un tip de bloc reprezentat printr-un șir de caractere.
*Harta conține cel puțin o sursă de apă și cel puțin o zonă verde.


== Exemplu 1 ==
== Exemplu 1 ==
;Intrare
;Intrare
5 <br>
1<br>
PUSH Dirt<br>
3<br>
PUSH Stone<br>
VVA<br>
POP<br>
AVV<br>
PUSH Wood<br>
VVV
PUSH Iron


;Iesire
;Iesire
['Dirt', 'Wood', 'Iron']
19


== Rezolvare ==
== Rezolvare ==
<syntaxhighlight lang="python" line>
<syntaxhighlight lang="python" line>
def citeste_date():
def numara_zona_supravietuire(harta, N):
     try:
     def dfs(i, j):
         n = int(input("Introduceți numărul de operațiuni (n): "))
         if i < 0 or i >= N or j < 0 or j >= N or harta[i][j] == 'A' or vizitat[i][j]:
        operatiuni = []
            return
         for _ in range(n):
        vizitat[i][j] = True
             operatiune = input().strip()
        dfs(i + 1, j)
             operatiuni.append(operatiune)
        dfs(i - 1, j)
        return n, operatiuni
        dfs(i, j + 1)
    except ValueError:
        dfs(i, j - 1)
        return None, None
 
    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)


def valideaza_date(n, operatiuni):
         return max_area
    if not (1 <= n <= 100):
         return False
    for operatiune in operatiuni:
        if not (operatiune.startswith("PUSH ") or operatiune == "POP"):
            return False
        if operatiune.startswith("PUSH ") and len(operatiune.split()) != 2:
            return False
        if operatiune.startswith("PUSH ") and not operatiune.split()[1].isalpha():
            return False
    return True


def proceseaza_operatiuni(n, operatiuni):
    max_area = 0
     stiva = []
     dp = [0] * N
     for operatiune in operatiuni:
 
         if operatiune.startswith("PUSH "):
     for i in range(N):
             _, bloc = operatiune.split()
         for j in range(N):
            stiva.append(bloc)
             if harta[i][j] == 'V':
        elif operatiune == "POP":
                 dp[j] += 1
            if stiva:
                 stiva.pop()
             else:
             else:
                 print("Eroare: stivă goală")
                 dp[j] = 0
     return stiva
        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():
def main():
     n, operatiuni = citeste_date()
     K = int(input().strip())
      
     N = int(input().strip())
     if n is None or operatiuni is None or not valideaza_date(n, operatiuni):
 
         print("Datele de intrare nu corespund restricțiilor impuse.")
    assert 2 <= N <= 1000, "N trebuie sa fie intre 2 si 1000"
         return
 
      
     harta = []
    print("Datele de intrare corespund restricțiilor impuse.")
    for _ in range(N):
     rezultat = proceseaza_operatiuni(n, operatiuni)
         row = list(input().strip())
     print(rezultat)
        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__":
if __name__ == "__main__":

Versiunea curentă din 2 iunie 2024 22:48

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