Rezolvare completă PbInfo #2496 road

Se consideră o matrice cu N linii și N coloane care memorează doar cifre. Liniile și coloanele sunt numerotate de la 1 la N. Se consideră de asemenea un vector v de lungime 10, în care v[i] = costul cifrei i (i = 0..9). Trebuie să determinăm un drum de la coloana 1 la coloana N, deci care pornește de la o componentă aflată pe coloana 1 la o componentă de pe coloana N și fiecare pas se face dintr-o poziție (i,j) într-una din pozițiile învecinate pe linie sau coloană, adică (i+1,j), (i-1,j), (i,j+1), (i,j-1), cu condiția să nu iasă din matrice. Costul unui astfel de drum este suma costurilor asociate componentelor prin care trece drumul.

Cerința

Să se determine numărul minim de cifre distincte prin care trece un drum de la coloana 1 la coloana N. Dacă există mai multe astfel de drumuri, atunci se va determina costul minim al unui astfel de drum.

Date de intrare

Fișierul de intrare road.in conține pe prima linie valoarea N. Pe a doua linie se află exact 10 numere naturale v[0], v[1], …, v[9] separate prin câte un spațiu. Pe următoarele N linii se află câte N cifre, fără spații între ele.

Date de ieșire

Fișierul de ieșire road.out va conține pe prima linie un număr natural K reprezentând numărul minim de cifre distincte prin care trece un drum de la coloana 1 la coloana N. Pe linia a doua se află un singur număr natural reprezentând costul minim al unui drum care trece prin K cifre distincte.

Restricții și precizări

  • 2 ≤ N ≤ 100
  • 1 ≤ v[i] ≤ 100, i=0..9

Exemplu

road.in

6
8 1 2 1 9 14 8 8 6 9
287566
123444
983070
071311
548739
353665

road.out

3
9

Explicație

Drumul este marcat cu fundal gri în matricea de mai jos și folosește doar trei cifre distincte (1, 2 și 3), iar costul drumului este 9.

De remarcat că mai există un drum care utilizează doar trei cifre distincte (format din toate elementele de pe ultima linie), dar are cost mai mare.

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

/*
   Implementare Dan Pracsiu
*/

#include <bits/stdc++.h>
#define nmax 105
#define oo 1000000000
#define inFile  "road.in"
#define outFile "road.out"
using namespace std;

struct PQ
{
    int x, y, val;
    bool operator < (const PQ &e) const
    {
        return val > e.val;
    }
};

int a[nmax][nmax], d[nmax][nmax], v[10], n;
int nrMinCif, dMin;
int dx[] = {0, 0, -1, 1};
int dy[] = {1, -1, 0, 0};
priority_queue<PQ> q;

void Citire()
{
    int i, j;
    char s[nmax];
    ifstream fin(inFile);
    fin >> n;
    for (i = 0; i < 10; i++)
        fin >> v[i];
    for (i = 1; i <= n; i++)
    {
        fin >> (s + 1);
        for (j = 1; j <= n; j++)
            a[i][j] = s[j] - '0';
    }
    fin.close();
}

void Bordare()
{
    int i;
    for (i = 0; i <= n + 1; i++)
        a[0][i] = a[n + 1][i] = a[i][0] = a[i][n + 1] = -1;
}

void InitD()
{
    int i, j;
    for (i = 1; i <= n; i++)
        for (j = 1; j <= n; j++)
            d[i][j] = oo;
}

int Lee(int V)
{
    PQ w;
    int i, j, x, y, k, M;
    InitD();
    for (i = 1; i <= n; i++)
        if (V & (1 << a[i][1]))
        {
            d[i][1] = v[a[i][1]];
            q.push({i, 1});
        }
    while (!q.empty())
    {
        i = q.top().x;
        j = q.top().y;
        q.pop();
        for (k = 0; k < 4; k++)
        {
            x = i + dx[k];
            y = j + dy[k];
            if (a[x][y] >= 0 && (V & (1<<a[x][y]))
                && d[x][y] > d[i][j] + v[a[x][y]])
            {
                w.x = x; w.y = y; w.val = d[i][j] + v[a[x][y]];
                d[x][y] = w.val;
                q.push(w);
            }
        }
    }
    M = oo;
    for (i = 1; i <= n; i++)
        M = min(M, d[i][n]);
    return M;
}

int NrCif(int n)
{
    int cnt = 0;
    while (n > 0)
    {
        cnt++;
        n = (n & (n - 1));
    }
    return cnt;
}

void Rezolvare()
{
    int V, D, c;
    nrMinCif = 10;
    dMin = oo;
    for (V = 1; V < 1024; V++)
    {
        c = NrCif(V);
        D = Lee(V);
        if (c < nrMinCif && D < oo)
        {
            nrMinCif = c;
            dMin = D;
        }
        else if (c == nrMinCif)
            dMin = min(dMin, D);
    }
    ofstream fout(outFile);
    fout << nrMinCif << "\n" << dMin << "\n";
    fout.close();
}

int main()
{
    Citire();
    Bordare();
    Rezolvare();
    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 #2496 road

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