Sunteți pe pagina 1din 5

Note de laborator Specializare

Algoritmi si structuri de date 2 Info 1

Laborator 9
Descriere: Diverse

1. Lacusta

Se considera o matrice dreptunghiulara cu m linii si n coloane, cu valori naturale. Traversam


matricea pornind de la coltul stanga-sus la coltul dreapta-jos. O traversare consta din mai multe
deplasari. La fiecare deplasare se executa un salt pe orizontala si un pas pe verticala. Un salt
ınseamna ca putem trece de la o celula la oricare alta aflata pe aceeasi linie, iar un pas ınseamna ca
putem trece de la o celula la celula aflata imediat sub ea. Exceptie face ultima deplasare (cea ın care
ne aflam pe ultima linie), cand vom face doar un salt pentru a ajunge ın coltul dreapta-jos, dar nu
vom mai face si pasul corespunzator. Astfel traversarea va consta din vizitarea a 2m celule.

Cerinta

Scrieti un program care sa determine suma minima care se poate obtine pentru o astfel de
traversare.

Datele de intrare

Fisierul de intrare lacusta.in contine pe prima linie doua numere naturale separate printr-un spatiu
m n, reprezentand numarul de linii si respectiv numarul de coloane ale matricei. Pe urmatoarele m
linii este descrisa matricea, cate n numere pe fiecare linie, separate prin cate un spatiu.

Datele de iesire

Fisierul de iesire lacusta.out va contine o singura linie pe care va fi scrisa suma minima gasita.

Restrictii si precizari
• 1 ≤ m, n ≤ 100
• Valorile elementelor matricei sunt numere intregi din intervalul [1, 255].

Pentru rezolvarea acestei probleme vom utiliza metoda programarii dinamice. Vom nota prin A
matricea data si vom construi o matrice B ale carei elemente bij vor contine sumele minime
necesare pentru a ajunge ın celula (i, j) pornind din celula (i − 1, j).

Vom completa initial elementele de pe a doua linie a matricei B. Valoarea b2,1 va fi ∞ deoarece ın
aceasta celula nu se poate ajunge. Valorile celorlalte elemente b2i vor fi calculate pe baza formulei:
b2,i = a1,1 + a1,i + a2,i.

Pentru celelalte linii, valorile bij vor fi calculate pe baza formulei: bi,j = ai,j + ai−1,j + min(bi−1,k),
ASD

unde k variaza ıntre 1 si n. Evident, relatia nu este valabila pentru elementul de pe coloana k care
corespunde minimului, deoarece nu se poate coborı direct, ci trebuie efectuat un salt orizontal. In
aceasta situatie vom alege al doilea minim de pe linia anterioara.

In final alegem minimul valorilor de pe ultima linie a matricei B (fara a lua ın considerare
elementul de pe ultima coloana a acestei linii) la care adaugam valoarea amn.

import java.io.*;
class Lacusta{

static final int oo=100000;


static int m,n;
static int[][] a,b; // 0 <= i <= m-1; 0 <= j <= n-1

public static void main(String[] args) throws IOException{


long t1,t2;
t1=System.currentTimeMillis();
int i,j;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(new
FileReader("lacusta.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(new
FileWriter("lacusta.out")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
a=new int[m][n];
b=new int[m][n];

for(i=0;i<m;i++)
for(j=0;j<n;j++){
st.nextToken();
a[i][j]=(int)st.nval;
}

for(i=0;i<m;i++)
for(j=0;j<n;j++)
b[i][j]=oo;
// prima linie (i=0) din b este oo
// a doua linie (i=1) din b

for(j=1;j<n;j++)
b[1][j]=a[0][0]+a[0][j]+a[1][j];

// urmatoarele linii din b


for(i=2;i<m;i++)
for(j=0;j<n;j++)
b[i][j]=a[i][j]+a[i-1][j]+minLinia(i-1,j);
// "obligatoriu" (!) si ultima linie (i=n-1) dar fara coborare

b[m-1][n-1]=minLinia(m-1,n-1)+a[m-1][n-1];
out.println(b[m-1][n-1]);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}// main()

static int minLinia(int ii, int jj){ // min pe linia=ii fara pozitia jj==col
int j,min=oo;
for(j=0;j<n;j++)
if(j!=jj)
if(b[ii][j]<min)
min=b[ii][j];
return min;
ASD

}// minLinia(...)
}// class

2. Lac

Un lac are forma cubica, cu latura M (numar natural). El este ımpartit ın M3 pozitii elementare. O
pozitie este identificata prin coordonatele n, l, c, ca ıntru-un spatiu tridimensional, unde: n
reprezinta nivelul (1 pentru cel din imediata apropiere a suprafetei apei, M pentru nivelul de pe
fundul lacului),

l reprezinta linia (linia 1 este linia cea mai apropiata de privitor)


c reprezinta coloana (coloana 1 este cea din stanga privitorului).

Exemple de deplasari elementare:

- din pozit¸ia (4, 2, 2) se poate ajunge la una din pozitiile: (3, 1, 1), (3, 1, 2),
(3, 1, 3), (3, 2, 1), (3, 2, 2), (3, 2, 3), (3, 3, 1), (3, 3, 2), (3, 3, 3);
- din pozitia (2, 1, 1) se poate ajunge ın una din pozitiile: (1, 1, 1), (1, 1, 2),
(1, 2, 1), (1, 2, 2).

Exista o casuta speciala, la suprafata apei, considerata pe nivelul 0 si anume cea ın care trebuie sa
ajunga ın final un scafandru ce pleaca de pe fundul lacului. In lac exista pozitii elementare
considerate ca fiind statii de lucru ce au de transmis la suprafata anumite mesaje. Aceste statii pot fi
oricate si pot fi dispuse oriunde ın cub (chiar si ın pozitia de plecare a scafandrului). Scafandrul se
poate deplasa din pozitia sa numai ıntr-o pozitie de pe nivelul imediat superior (de la nivelul i la
nivelelul i−1, pentru 1 ≤ i ≤ m) si care difera ca linie si coloana cu cel mult 1 fata de pozitia
precedenta. Deci dintr-o pozitie se poate ajunge (vezi figura) ın maxim 9 pozitii pe nivelul imediat
superior. Scafandrul se afla pe fundul lacului la coordonatele m, l1, c1. El trebuie sa ajunga la
suprafata lacului (adica deasupra primului nivel al cubului), ıntr-o pozitie de coordonate 0, l2, c2,
adica imediat deasupra pozitiei 1, l2, c2 din cub.

Cerinta:

Trebuie determinat ce drum trebuie sa aleaga scafandrul pentru a duce la destinatie cat mai multe
mesaje, respectand restrictiile din enunt

Date de intrare:

Fisierul de intrare LAC.IN, contine: pe prima linie cinci numere m l1 c1 l2 c2 despartite prin cate un
spatiu, reprezentand m dimensiunea cubului, l1, c1 linia si coloana pozitiei de plecare, iar l2, c2 linia
si coloana pozitiei de sosire; pe a doua linie numaul y de statii din lac; pe urmatoarele y linii seturi
de cate patru numere n l c p.
ASD

Primele trei numere n l c reprezinta coordonatele unei statii iar ultimul numar p reprezinta numarul
de mesaje ce trebuiesc transmise de statia respectiva;

Datele de iesire:

Iesirea se va face ın fisierul LAC.OUT ın formatul urmator:

pe prima linie se va scrie numarul maxim de mesaje aduse la suprafata. pe urmatoarele m + 1 linii
se vor scrie seturi de patru numere n l c p, primele trei numere reprezentand coordonatele statiilor
vizitate (ın ordinea parcurgerii), iar ultimul numar reprezentand numarul de mesaje culese din statia
respectiva. Prima linie din cele m + 1 reprezinta punctul de plecare, iar ultima punctul de sosire
(nivelul 0).

Restrictii:

2 ≤ M ≤ 20
0 ≤ P ≤ 100

import java.io.*;
class Lac{
static int m,ns; // dim lac, nr statii
static int[][][] a; // lacul ... cu nr mesaje
static int[][][] c; // suma max mesaje pana aici
static int[][][] d; // din ce directie a ajuns
static int l1,c1,l2,c2; // pozitii initiale si finale (linie,coloana)
static PrintWriter out;
static StreamTokenizer st;

public static void main(String[] args) throws IOException{


citire();
rezolvare();
afisare();
}// main(...)

static void citire() throws IOException{


int niv,lin,col,s;
st=new StreamTokenizer(
new BufferedReader(new FileReader("lac.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); l1=(int)st.nval;
st.nextToken(); c1=(int)st.nval;
st.nextToken(); l2=(int)st.nval;
st.nextToken(); c2=(int)st.nval;
a=new int[m+1][m+1][m+1];
c=new int[m+1][m+1][m+1];
d=new int[m+1][m+1][m+1];
st.nextToken(); ns=(int)st.nval;

for(s=1;s<=ns;s++){ // statia
st.nextToken(); niv=(int)st.nval;
st.nextToken(); lin=(int)st.nval;
ASD

st.nextToken(); col=(int)st.nval;
st.nextToken(); a[niv][lin][col]=(int)st.nval;
}
}// citire()

static void rezolvare(){


int i,j,niv,lin,col;

for(niv=m-1;niv>=0;niv--)
for(lin=1;lin<=m;lin++)
for(col=1;col<=m;col++){
c[niv][lin][col]=-1;
for(i=-1;i<=1;i++){
if((lin+i<1)||(lin+i>m)||(lin+i<l1-(m-niv-1))||(lin+i>l1+(m-niv-
1))) continue;

for(j=-1;j<=1;j++){
if((col+j<1)||(col+j>m)||(col+j<c1-(m-niv-1))||(col+j>c1+(m-niv-1)))
continue;

if(c[niv][lin][col]<c[niv+1][lin+i][col+j]+a[niv+1][lin+i][col+j]){
c[niv][lin][col]=c[niv+1][lin+i][col+j]+a[niv+1][lin+i][col+j];
d[niv][lin][col]=(i+1)*3+(j+2);
}
}// for j/col
}// for i/lin
}// col
}// rezolvare

static void afisare() throws IOException{


out=new PrintWriter(new BufferedWriter(new FileWriter("lac.out")));
out.println(c[0][l2][c2]);
drum(0,l2,c2);
out.close();
}// afisare()

static void drum(int niv, int lin, int col) throws IOException{
int i,j;
i=(-1+d[niv][lin][col])/3; // 0,1,2
j=(-1+d[niv][lin][col])%3; // 0,1,2
i--;
j--;
if(niv<m) drum(niv+1,lin+i,col+j);
out.println(niv+" "+lin+" "+col+" "+a[niv][lin][col]);
}// drum(...)
}// class

3. Probleme

Un teren este reprezentat sub forma unei matrice A cu m linii si n coloane.Elementele aij reprezinta
cotele portiunilor din teren.O minge de golf se gaseste pe o portiune cu o cota cunoscuta. Sa se
precizeze toate traseele posibile pe care le poate urma bila spre a iesi din teren, stiind ca mingea se
poate deplasa pe orice portiune de teren invecinata ,cu o cota strict mai mica decat cea a terenului
pe care se gaseste. Realizati un program care afiseaza traseele posibile.

S-ar putea să vă placă și