Documente Academic
Documente Profesional
Documente Cultură
Laborator 12
Descriere: Probleme propuse la olimpiade judetene si nationale de informatica
O triangulatie a unui poligon convex este o multime formata din diagonale ale poligonului care nu
se intersecteaza ın interiorul poligonului ci numai ın varfuri si care ımpart toata suprafata
poligonului ın triunghiuri. Fiind dat un poligon cu n varfuri notate 1, 2, ..., n sa se genereze toate
triangulatiile distincte ale poligonului. Doua triangulatii sunt distincte daca difera prin cel putin o
diagonala.
Datele de intrare
In fisierul text triang.in se afla pe prima linie un singur numar natural reprezentand valoarea lui n
(n ≤ 11).
Datele de iesire
Exemplu
Observatie
Numarul de triangulatii distincte pentru un poligon cu n varfuri este dat de numarul lui Catalan
Cn-2. Figura de mai jos ilustreaza grafic solutia problemei “In cate moduri putem diviza un poligon
cu n varfuri in n-2 triunghiuri daca consideram diversele orientari ca fiind separate”.
ASD
Rezolvare
import java.io.*;
class Triangulatii{
st.nextToken();
n=(int)st.nval;
ndt=n-3;
nd=n*(n-3)/2;
else{
out.println(catalan(n-2)); //numarul de triangulatii
ASD
out.close();
t2=System.currentTimeMillis();
System.out.println("nsol = "+nsol+" Timp = "+(t2-t1));
}
// calculeaza diagonalele
static void diagonale(){
int i,j;
int k=0; //index diagonala
// diagonale cu varful in 1
i=1;
for(j=3;j<=n-1;j++) {
v1[++k]=i;
v2[k]=j;
}
// restul de diagonale
for(i=2;i<=n-2;i++)
for(j=i+2;j<=n;j++){
v1[++k]=i;
v2[k]=j;
}
}
for(j=1;j<=k-1;j++)
if(((v1[x[j]]<v1[i])&&(v1[i]<v2[x[j]])&&(v2[x[j]]<v2[i]))||
((v1[i]<v1[x[j]])&&(v1[x[j]]<v2[i])&&(v2[i]<v2[x[j]])))
return true;
return false;
}
if(k<ndt) f(k+1);
else afisarediag();
}
}
int rez;
int i,j;
int d;
ASD
// calcul combinari
int[] x=new int[n+1];
int[] y=new int[n+1];
for(i=2;i<=n;i++) x[i]=n+i;
for(j=2;j<=n;j++) y[j]=j;
for(j=2;j<=n;j++)
for(i=2;i<=n;i++){
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=2;i<=n;i++) rez*=x[i];
return rez;
}
2. Alee
Parcul orasului a fost neglijat mult timp, astfel ca acum toate aleile sunt distruse. Prin urmare, anul
acesta Primaria si-a propus sa faca reamenajari. Parcul are forma unui patrat cu latura de n metri si
este ınconjurat de un gard care are exact doua porti. Proiectantii de la Primarie au realizat o harta a
parcului si au trasat pe harta un caroiaj care ımparte parcul ın nxn zone patrate cu latura de 1 metru.
Astfel harta parcului are aspectul unei matrice patratice cu n linii si n coloane. Liniile si respectiv
coloanele sunt numerotate de la 1 la n. Elementele matricei corespund zonelor patrate de latura 1
metru. O astfel de zona poate sa contina un copac sau este libera. Edilii orasului doresc sa paveze
cu un numar minim de dale patrate cu latura de 1 metru zonele libere (fara copaci) ale parcului,
astfel ıncat sa se obtina o alee continua de la o poarta la alta.
Cerinta
Scrieti un program care sa determine numarul minim de dale necesare pentru construirea unei alei
continue de la o poarta la cealalta.
Date de intrare
Fisierul de intrare alee.in contine pe prima linie doua valori naturale n si m separate printr-un
spatiu, reprezentand dimensiunea parcului, respectiv numarul de copaci care se gasesc ın parc.
Fiecare dintre urmatoarele m linii contine cate doua numere naturale x si y separate printr-un
spatiu, reprezentand pozitiile copacilor ın parc (x reprezinta linia, iar y reprezinta coloana zonei ın
care se afla copacul). Ultima linie a fisierului contine patru numere naturale x1 y1 x2 y2, separate
prin cate un spatiu, reprezentand pozitiile celor doua porti (x1, y1 reprezinta linia si respective
coloana zonei ce contine prima poarta, iar x2, y2 reprezinta linia si respectiv coloana zonei ce
contine cea de a doua poarta).
ASD
Date de iesire
Fisierul de iesire alee.out va contine o singura linie pe care va fi scris un numar natural care
reprezinta numarul minim de dale necesare pentru construirea aleii.
Restrictii si precizari
1 ≤ n ≤ 175
1≤m<n∗n
Aleea este continua daca oricare doua placi consecutive au o latura comuna.
Aleea ıncepe cu zona unde se gaseste prima poarta si se termina cu zona
unde se gaseste cea de a doua poara.
Pozitiile portilor sunt distincte si corespund unor zone libere.
Pentru datele de test exista ıntotdeauna solutie.
Exemplu
Indicatii de rezolvare
Rezolvarea se bazeaza pe algoritmul lui Lee (vezi Laborator 11). Pentru reprezentarea
informatiilor vom utiliza o matrice A ın care initial vom retine valoarea −2 pentru zonele libere,
respectiv valoarea −1 pentru zonele ın care se afla un copac. Ulterior, pe masura ce exploram
matricea ın scopul determinarii unei alei de lungime minima vom retine ın matrice pentru pozitiile
explorate un numar natural care reprezinta distanta minima de la pozitia primei porti la pozitia
respectiva (exprimata ın numarul de dale necesare pentru construirea aleei).
Vom parcurge matricea ıncepand cu pozitia primei porti. Pozitiile din matrice care au fost explorate
le vom retine ıntr-o coada, ın ordinea explorarii lor.
La fiecare pas vom extrage din coada o pozitie (x, y), vom explora toti cei 4 vecini liberi
neexplorati ai pozitiei extrase si ıi vom introduce ın coada. Cand exploram un vecin, retinem ın
matricea A pe pozitia sa distanta minima (1 +A[x][y]). Procedeul se repeta cat timp coada nu este
vida si poziia ın care se afla cea de a doua poarta nu a fost explorata. Rezultatul se va obtine ın
matricea A, pe pozitia celei de a doua porti.
ASD
import java.io.*;
class Alee{
static int n, m;
static int nrDale;
citire();
bordare();
determinNrDale();
out.println(nrDale);
System.out.println("Nr minim de dale = " + nrDale);
out.close();
}// main
// pozitie intiala
int pozX;
int pozY;
//initializare coada
pozX=inX;
pozY=inY;
A[inX][inY]=1;
qx[incC]=pozX;
qy[incC]=pozY;
ASD
//parcurgere parc
while(incC<=sfC && A[outX][outY]==-2){
//extragere element din coada
pozX=qx[incC];
pozY=qy[incC];
incC++;
if(A[outX][outY]==-2)
System.out.println("Nu exista solutie");
else nrDale=A[outX][outY];
}
st.nextToken();
m=(int)st.nval;
st.nextToken(); outX=(int)st.nval;
st.nextToken(); outY=(int)st.nval;
}
}// class
Cateva broscute mergand la plimbare si descoperind un mozaic asemanator unei table de sah de
dimensiune nxn, au inventat un joc cu urmatoarele reguli: fiecare broscuta porneste din centrul
patratelului aflat ın coltul din stanga sus al tablei, trece prin fiecare patratel al mozaicului, si se
ıntoarce ın patratelul de unde a pornit, poate sari din centrul unui patratel oarecare ın centrul
oricaruia din patratelele vecine aflate ın directiile: N, S, E, V, NE, NV, SE, SV, si daca se unesc
centrele patratelelor ın ordinea ın care au fost parcurse, se obtine o linie ınchisa care nu trebuie sa
se autointersecteze.
Una din broscute - mai nechibzuita - face pariu pe greutatea ei ın musculite, ca poate gasi o ordine
ın care sa acopere cu sarituri mozaicul astfel ıncat, lungimea drumului parcurs sa nu poata fi
depasita. Lungimea este ın sens geometric: drumul dintre centrele a doua patrate cu o latura
comuna este 1, iar ıntre centrele a doua patrate ce au doar un varf comun, distanta este √2.
Cerinta
Din pacate, broscuta nu prea stie cum sa procedeze, asa ca trebuie realizat in program care sa indice
ordinea ın care trebuie sa parcurga patratelele tablei astfel ıncat sa nu piarda pariul.
Date de intrare
Date de iesire
In fisierul FROG.OUT se vor scrie, pe linia i (i = 1...n2 + 1), doua perechi de valori separate printr-
un spatiu, reprezentand coordonatele patratelului unde trebuie sa sara broscuta la pasul i (se
considera ca ın coltul din stanga sus avem coordonatele 1, 1 iar localizarea unui patratel se face ca
ın matrice).
Restrictii
2 ≤ n ≤ 250
Exemplu
Frog.in Frog.out
4 1 1
2 1
2 2
3 1
4 1
3 2
2 3
3 3
4 2
4 3
4 4
3 4
2 4
1 4
1 3
1 2
1 1
ASD
Rezolvare
import java.io.*;
class Broscute{
st.nextToken(); n=(int)st.nval;
if(n==2){
out.println(1+" "+1);
out.println(2+" "+1);
out.println(2+" "+2);
out.println(1+" "+2);
out.println(1+" "+1);
}
else{
i=1;
j=1;
out.println(i+" "+j); // start
i++;
out.println(i+" "+j); // S
j++;
out.println(i+" "+j); // E
while(j>1) {
i++;
j--;
out.println(i+" "+j);
} // SV
i++;
out.println(i+" "+j); // S
while(i>2) {
i--;
j++;
out.println(i+" "+j);
} // NE
}
if(j==n-2) {
j++;
out.println(i+" "+j);
} // E
else {
i++;
out.
println(i+" "+j);
} // S
while(i<n) {
ASD
i++;
j--;
out.println(i+" "+j);
} // SV
j++;
out.println(i+" "+j); // E
while(j<n-1) {
i--;
j++;
out.println(i+" "+j);
} // NE
i++;
out.println(i+" "+j); // S
}
i++;
j--;
out.println(i+" "+j); // SV
j++;
out.println(i+" "+j); // E
j++;
out.println(i+" "+j); // E
for(i=n-1;i>=1;i--)
out.println(i+" "+n); // N
for(j=n-1;j>=1;j--)
out.println(1+" "+j); // V
}
System.out.println("Gata. Verificati fisierul frog.out");
out.close();
}// main(...)
}// class