Rezolvare completă PbInfo #2127 ninjago

După ce eroii ninja l-au învins pe Nadakhan, de ziua celor dispăruți Zane trebuia să păzească cele n păpuși din muzeu. Între aceste păpuși există m coridoare pe care se poate circula în ambele sensuri. Se garantează faptul că pe cele m coridoare Zane poate ajunge la fiecare dintre cele n păpuși. Skulkiu, având la dispoziție 5 tipuri de obstacole A, B, C, D, E, încearcă să-l oprească pe Zane punând pe fiecare coridor câte 4 obstacole. Zane poate distruge obstacolele de tip A, B, C și D, dar nu poate să distrugă obstacolele de tipul E. Pentru a distruge un obstacol de tipul A arma lui Zane are nevoie de 1 unitate de energie, pentru a distruge un obstacol de tipul B de 2 unități de energie, pentru a distruge un obstacol de tipul C de 3 unități de energie, iar pentru a distruge un obstacol de tipul D de 4 unități de energie. Datorită dispozitivului cu care Skulkiu amplasează obstacolele pe coridor, cele patru obstacole de pe acelaşi coridor au o adâncime din ce în ce mai mare, ceea ce implică faptul că pentru a distruge al doilea obstacol amplasat pe coridor este nevoie de 5 ori mai multă energie decât cea obișnuită, pentru a distruge cel de-al treilea obstacol amplasat pe coridor este nevoie de 25 ori mai multă energie decât cea obișnuită, iar pentru a distruge al patrulea obstacol amplasat pe acelaşi coridor este nevoie de 125 de ori mai multă energie decât cea obișnuită. Indiferent de sensul de parcurgere al coridorului de către Zane pentru a înlătura obstacolele, energia consumată este aceeaşi, aceasta depinzând doar de ordinea în care au fost amplasate obstacolele de către Skulkiu. Zane nu va înlătura obstacolele de pe toate coridoarele ci doar strictul necesar pentru a avea acces la fiecare păpușă. Zane dorește să-i lase pe ceilalți ninja să se antreneze așa că face în așa fel încât ajutorul pentru distrugerea obstacolelor de tip E să fie minim și apoi ca el să utilizeze un număr minim de unități de energie. Pentru coridoarele pe care se află obstacole de tip E Zane consumă energie doar pentru obstacolele de tip A, B, C şi D. Inițial Zane se află lângă păpușa 1.

Cerințe

  1. Precizați la câte dintre cele n păpuși poate ajunge Zane înainte de a cere ajutorul celorlalți ninja.
  2. Precizați pentru eliberarea câtor coridoare trebuie să ceară ajutor extern pentru a reuși să ajungă la toate cele n păpuși și câte obstacole de tip E sunt în total pe aceste coridoare.
  3. Precizați care este numărul minim de unități de energie utilizate.

Date de intrare

Fișierul de intrare ninjago.in conține pe prima linie v care poate avea doar valorile 1, 2 sau 3 reprezentând cerința care va fi rezolvată. Fișierul ninjago.in conține pe a doua linie numerele naturale n și m separate printr-un spațiu, iar pe următoarele m linii pentru fiecare coridor două numere naturale separate printr-un spațiu reprezentând cele două păpuși între care se circulă pe coridorul respectiv urmate de un spaţiu și patru litere corespunzătoare celor patru tipuri de obstacole în ordinea în care Skulkiu le-a amplasat pe coridorul respectiv. Între cele patru litere nu se află nici un spaţiu.

Date de ieșire

Dacă valoarea lui v este 1 atunci fișierul de ieșire ninjago.out va conține pe prima linie numai numărul păpușilor la care poate ajunge Zane înainte de a cere ajutorul celorlalți ninja.

Dacă valoarea lui v este 2 atunci fișierul de ieșire ninjago.out va conține pe prima linie numărul de coridoare pe care nu le poate elibera singur și pe a doua linie numărul total de obstacole de tip E de pe aceste coridoare.

Dacă valoarea lui v este 3 atunci fișierul de ieșire ninjago.out va conține pe prima linie numai numărul minim de unități de energie utilizate.

Restricții și precizări

  • 1 ≤ N,M ≤ 31200;
  • Pentru rezolvarea corectă a primei cerințe se acordă 20 de puncte;
  • Pentru rezolvarea corectă a celei de-a doua cerințe se acordă 40 de puncte;
  • Pentru rezolvarea corectă a celei de-a treia cerințe se acordă 30 de puncte.
  • În concurs s-au acordat 10 puncte din oficiu. Pe site se acordă 10 puncte pentru exemple.

Exemplul 1

ninjago.in

1
9 15
1 2 CBAA 
1 5 ABAA 
2 6 CBEA 
2 7 ACBA 
2 5 CBEA 
3 4 ABAA 
3 7 AECE 
3 8 CBAC 
3 9 ECEE 
4 8 DBAD 
4 9 ECEB 
5 6 CBAD 
5 7 BAAD 
6 7 CBAA 
7 8 ECEB 

ninjago.out

5

Exemplul 2

ninjago.in

2
9 15
1 2 CBAA 
1 5 ABAA 
2 6 CBEA 
2 7 ACBA 
2 5 CBEA 
3 4 ABAA 
3 7 AECE 
3 8 CBAC 
3 9 ECEE 
4 8 DBAD 
4 9 ECEB 
5 6 CBAD 
5 7 BAAD 
6 7 CBAA 
7 8 ECEB

ninjago.out

2
4

Exemplul 3

ninjago.in

3
9 15
1 2 CBAA 
1 5 ABAA 
2 6 CBEA 
2 7 ACBA 
2 5 CBEA 
3 4 ABAA 
3 7 AECE 
3 8 CBAC 
3 9 ECEE 
4 8 DBAD 
4 9 ECEB 
5 6 CBAD 
5 7 BAAD 
6 7 CBAA 
7 8 ECEB

ninjago.out

1593

Explicații

Explicația exemplului 1

Zane va putea ajunge la nodurile 1, 2, 5, 6, 7. eliberând singur coridoarele (1,2), (1,5), (2,7) și (6,7)

Explicația exemplului 2

Zane trebuie să ceară ajutor pentru eliberarea a 2 coridoare pentru a putea ajunge la toate cele 9 păpuși.
Zane are nevoie de ajutor pentru a elibera coridoarele (3,7) și (4,9). Pe fiecare dintre aceste 2 coridoare se află câte 2 obstacole de tip E, deci în total 4 obstacole de tip E.

Explicația exemplului 3

Zane va consuma minim 1593 de unități de energie astfel:

  • 163 pentru coridorul (1,2)
  • 161 pentru coridorul (1,5)
  • 191 pentru coridorul (2,7)
  • 161 pentru coridorul (3,4)
  • 76 pentru coridorul (3,7)
  • 413 pentru coridorul (3,8)
  • 265 pentru coridorul (4,9)
  • 163 pentru coridorul (6,7)

Pentru coridorul (4,9) obstacolele sunt ECEB, deci Zane va consuma 0+3*5+0*25+2*125=265 unități de energie.

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

#include <iostream>
#include <fstream>


using namespace std;

short v;
int n,m;
struct nod
  { int e1,e2;
    nod* urm;
  };

nod* lm[2501];

int T[31202], H[31202];

void citire()
 {
   ifstream fin("ninjago.in");
   int i,j,p5,c;
   char o;
   nod *p;
   fin >> v;
   fin >> n >> m;
   for (i=156;i<=2500;i++)
        lm[i]=NULL;
   for (int i = 1; i <= m; i++)
    { p=new nod;
      fin >> p->e1 >> p->e2;
      c=0; p5=1;
      for (int j = 0; j < 4; j++)
        {
          fin >> o;
          switch (o)
            {
              case 'A': c+=p5;break;
              case 'B': c+=2*p5;break;
              case 'C': c+=3*p5;break;
              case 'D': c+=4*p5;break;
              case 'E': c+=625;
            }
           p5*=5;
        }
      p->urm=lm[c];
      lm[c]=p;
    }
  fin.close();
 }

int radacina(int x)
  {
      int r,y;
      r=x;
      while (T[r]!=r)
        r=T[r];
      while (T[x]!=x)
        {
          y=T[x];
          T[x]=r;
          x=y;
        }
      return r;
  }

void UnesteArbori(int x, int y)
  {
    if (H[x]>H[y])
       T[y]=x;
    else T[x]=y;
    if (H[x]==H[y])
        H[y]++;
  }

int main()
{   ofstream fout("ninjago.out");

    int i,j,nn, ma,obst,r1;
    long cost;
    nod *p;
    citire();

    for (i=1;i<=n;i++)
      {
        T[i]=i; H[i]=1;
      }

    ma=0, cost=0, obst=0;

    i=156;
    while (ma<n-1 && i<625)
    {   p=lm[i];
        while (ma<n-1 && p)
         {
           if (radacina(p->e1)!=radacina(p->e2))
             {
                ma++;
                cost+=i;
                UnesteArbori(radacina(p->e1),radacina(p->e2));
             }
            p=p->urm;
         }
        i++;
    }
   if (ma==n-1)
       switch (v)
         { case 1:
             fout<<n<<'\n'; break;
           case 2:
              fout<<"0" << endl <<"0"; break;
           case 3: fout << cost;
         }
      else
      {
          if (v==1)
            {
              nn=0;
              r1=radacina(1);
              for (j = 1; j <= n; j++)
                 if (radacina(j)==r1) nn++;
              fout << nn;
            }
           else
             {
                nn=n-1-ma;
                while (ma<n-1)
                  {
                    p=lm[i];
                    while (ma<n-1 && p)
                      { if (radacina(p->e1)!=radacina(p->e2))
                          {
                            ma++;
                            cost+=i%625;
                            obst+=i/625;
                            UnesteArbori(radacina(p->e1),radacina(p->e2));
                          }

                         p=p->urm;
                      }
                    i++;
                  }

                if (v==2) fout <<nn << endl << obst;
                   else fout << cost;
             }
      }
    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 #2127 ninjago

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