Rezolvare completă PbInfo #727 Joc1

Atunci când este plictisit, Costel inventează jocuri logice şi încearcă să le rezolve. Într-o zi Costel ia o tablă dreptunghiulară împărţită în M*N pătrăţele identice, asemănătoare unei table de şah, şi aşează pe aceasta cuburi identice astfel încât, pe fiecare pătrat al tablei să se afle cel puţin un cub şi cel mult 10 cuburi suprapuse. Costel determină numărul minim de cuburi aşezate pe o poziţie a tablei, notat cu MIN.

El defineşte noţiunea de mutare astfel: alege patru pătrăţele învecinate, care formează un pătrat compus din 2*2 pătrăţele şi ridică toate cuburile de pe aceste poziţii astfel ca, pe fiecare dintre cele patru pătrăţele, să existe un număr de cuburi egal cu MIN. Efortul necesar efectuării mutării este egal cu MAX-MIN, unde MAX reprezintă numărul maxim de cuburi aflat pe unul dintre cele patru pătrăţele alese.

Scopul jocului este acela de a obţine acelaşi număr de cuburi, egal cu valoarea MIN, pe fiecare pătrăţel de pe tablă, efectuând un şir de mutări ce necesită un efort total minim. Efortul total depus pentru rezolvarea jocului este egal suma eforturilor mutărilor efectuate.

Cerința

Determinaţi valoarea efortului total minim depus pentru rezolvarea jocului.

Date de intrare

Fişierul de intrare joc1.in are următoarea structură:

  • pe prima linie se află două numere naturale M şi N, separate printr-un singur spaţiu, reprezentând numărul liniilor, respectiv numărul coloanelor tablei de joc.
  • pe următoarele M linii se află câte N numere naturale, separate prin câte un spaţiu, reprezentând numărul iniţial de cuburi aflate pe fiecare pătrăţel al tablei de joc.

Date de ieșire

Fișierul de ieșire joc1.out va conține un singur număr natural reprezentând valoarea efortului total minim.

Restricții și precizări

  • M şi N sunt numere naturale mai mari sau egale cu 2 cu proprietatea că 4 ≤ M x N ≤ 18
  • Numărul cuburilor plasate pe o poziţie a tablei este un număr natural între 1 şi 10.

Exemplu

joc1.in

3 4
2 3 2 2
2 4 3 2
3 2 4 2

joc1.out

4

Explicație

Minimul este 2. O succesiune optimă de mutări poate fi:

  • Mutarea 1: Se aleg poziţiile (2,2), (2,3), (3,2) şi (3,3). Efortul este 4 – 2 = 2
  • Mutarea 2: Se aleg poziţiile (1,1), (1,2), (2,1) şi (2,2). Efortul este 3 – 2 = 1
  • Mutarea 3: Se aleg poziţiile (2,1), (2,2), (3,1) şi (3,2). Efortul este 3 – 2 = 1

Efortul total este 4.

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 Joc1:

/* solutia 1 - 100p*/
#include <iostream>
#include <fstream>

#define IN  "joc1.in"
#define OUT "joc1.out"
#define Nmax 10
#define NivMax 11
#define MaxQ 100001

using namespace std;
typedef short int Mat[10][10];
  
Mat T, C[MaxQ];
int E[MaxQ], p, u;
int M,N, NrBuf;
int NivMin, n, gata;

int maxim(int a, int b)
{
   return a<b ? b : a;   
}

void copy(Mat T, Mat D)
{
   int i,j;  
   for(i=1;i<=M;i++)
     for(j=1;j<=N;j++) T[i][j] = D[i][j];
}

int final(int p)
{
   //verific daca am o configuratie finala 
   int i,j;  
   for(i=1;i<=M;i++)
     for(j=1;j<=N;j++) 
       if(C[p][i][j] != NivMin) return 0;
   return 1;
}

int exista(int u)
{
   //verific daca a o configuratie a mai aparut 
   int i,j,k,ok;  
   for(k=u-1;k>1;k--)
   {
      ok=1; 
      for(i=1;i<=M;i++)
       for(j=1;j<=N;j++) 
         if(C[u][i][j] != C[k][i][j]) ok=0;
       if(ok && E[k]<=E[u]) return  1;
   }         
   return 0;
}

int main()
{
   int i,j, Pi, Pj;
   ifstream F(IN);
   ofstream G(OUT);
   //citesc datele de intrare, calculand nivelul minim
   NivMin = NivMax;
   F>>M>>N;
   for(i=1;i<=M;i++)
     for(j=1;j<=N;j++) 
     {
        F>>T[i][j];
        if(T[i][j]<NivMin) NivMin = T[i][j];
     }
   F.close();
  
   //incep jocul
   n = (M-1)*(N-1);
   gata = 0; 
   NrBuf = 1000000;
   //coada contine configuratia initiala
   p=u=1;
   copy(C[u],T);
   E[u] = 0;
   //expandez coada
   while(p<=u)
   {
      if(final(p)) {if(E[p]<NrBuf) NrBuf = E[p];}
      else
        for(i=1; i<=n; i++) 
         {
             u++;
             Pi = i/(N-1)+1;                
             if(i%(N-1) == 0) Pi=Pi-1;
             Pj = (i%(N-1) == 0 ? N-1 : i%(N-1));
             E[u] = E[p] + maxim(maxim(C[p][Pi][Pj]- NivMin,C[p][Pi][Pj+1]- NivMin), maxim(C[p][Pi+1][Pj]- NivMin, C[p][Pi+1][Pj+1]- NivMin));                  
             copy(C[u],C[p]);
             C[u][Pi][Pj] = C[u][Pi][Pj+1] = C[u][Pi+1][Pj] = C[u][Pi+1][Pj+1] = NivMin;
             if(final(u)) {if(E[u]<NrBuf) NrBuf = E[u];} 
             if(exista(u)) u--;
         } 
       p++;       
         
   }    
   G<<NrBuf<<'\n'; 
   G.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 #727 Joc1

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #727 Joc1 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!