Primer parcial de EDA Facultad de Informática de Valencia 7

Transcripción

Primer parcial de EDA Facultad de Informática de Valencia 7
Primer parcial de EDA
Facultad de Informática de Valencia
7 de junio de 2007 – Duración 2 horas
No olvides poner el nombre. No utilices lápiz ni tinta roja. Se piden siempre soluciones eficientes.
Pregunta 1 (2.5 puntos) Sean dos vectores de enteros A y B, de talla n, n > 0, tal que A contiene una secuencia
estrictamente decreciente y B contiene una secuencia estrictamente creciente. Sabemos que existe un i, 0 ≤ i < n tal
que A[i] = B[i]. Por ejemplo, en los vectores:
A
0
20
1
12
2
8
3
7
4
5
5
0
6
-1
7
-3
B
0
-7
1
-5
2
8
3
10
4
12
5
13
6
26
7
70
se cumple que A[2] = B[2].
Se pide:
Una función “Divide y vencerás” recursiva que calcule en tiempo O(log n) el valor i para el cual A[i] = B[i].
El perfil de la función debe ser:
i n t c o r t e ( i n t ∗A, i n t ∗B , i n t l , i n t r )
donde l y r indican respectivamente los lı́mites izquierdo y derecho de los vectores A y B entre los cuales se
está realizando la búsqueda.
Justifica adecuadamente el coste de la función escrita.
¿Cuál es la llamada inicial a la función?
Importante: Se considerará incorrecta una función que realice una búsqueda de coste lineal.
Solución
i n t c o r t e ( i n t ∗A, i n t ∗B , i n t l , i n t r ) {
i f ( l == r ) return l ;
i n t m = ( l+r ) / 2 ;
i f (A[m] == B [m] ) return m;
i f (A[m] > B [m] )
return c o r t e (A, B , m+1 , r ) ;
return c o r t e (A, B , l , m−1) ;
}
La llamada inicial a este algoritmo será:
i n t c = c o r t e (A, B , 0 , n−1) ;
El coste del algoritmo es claramente O(log n) puesto que estamos realizando básicamente un búsqueda dicotómica. La
relación de recurrencia asociada a este algoritmo es la siguiente:
(
cte,
si n ≤ 1;
T (n) =
T (n/2) + θ(1), si n > 1
Donde n es r − l + 1. Podemos aplicar el teorema visto en clase para los valores a = 1, b = 2 y k = 0 porque a ≥ 1 y
b > 1. Como a = bk el coste será O(nk log n) = O(log n).
Pregunta 2 (3.5 puntos) Dada la siguiente implementación de un árbol binario:
c l a s s nodo {
public :
int v a l o r ;
nodo ∗ i z q , ∗ d e r ;
};
c l a s s a r b o l { // á r b o l b i n a r i o
public :
nodo ∗ r a i z ;
a r b o l ( ) { r a i z = 0 ; } ; // c o n s t r u c t o r
˜ arbol () ;
. . . // o t r o s métodos
bool e s a r b o l b i n a r i o ( ) ; // e j e r c i c i o de examen
i n t n o d o s c o n u n h i j o ( ) ; // e j e r c i c i o de examen
};
Implementa el método es_arbol_binario de la clase arbol que determine eficientemente si el árbol binario es
un árbol binario de búsqueda.
Solución
bool nodo : : e s a r b o l b i n a r i o ( ) {
i f ( ( i z q && i z q −>v a l o r > v a l o r ) | |
( d e r && der−>v a l o r < v a l o r ) )
return f a l s e ;
i f ( i z q && ! i z q −>e s a r b o l b i n a r i o ( ) ) return f a l s e ;
i f ( d e r && ! der−>e s a r b o l b i n a r i o ( ) ) return f a l s e ;
return true ;
}
bool a r b o l : : e s a r b o l b i n a r i o ( ) {
return ( ( r a i z ==0) | | r a i z −>e s a r b o l b i n a r i o ( ) ) ;
}
Implementa el método nodos_con_un_hijo de la clase arbol que cuente el número de nodos que tienen un solo
hijo.
Solución
i n t nodo : : n o d o s c o n u n h i j o ( ) {
int contador = 0 ;
i f ( ( i z q && ! d e r ) | | ( ! i z q && d e r ) ) //
c o n t a d o r ++;
i f ( i z q ) c o n t a d o r += i z q −>n o d o s c o n u n
i f ( d e r ) c o n t a d o r += der−>n o d o s c o n u n
return c o n t a d o r ;
}
int a r b o l : : n o d o s c o n u n h i j o ( ) {
return ( r a i z ==0) ? 0 : r a i z −>n o d o s c o n
}
también i f ( ( i z q !=0) ˆ ( d e r !=0) )
hijo () ;
hijo () ;
un hijo () ;
Pregunta 3 (4 puntos) Tenemos una imagen en blanco y negro guardada en un fichero con el siguiente formato:
9
0
0
0
0
0
0
0
1
1
8
0
1
1
1
1
1
0
1
1
1
0
1
0
1
0
0
0
0
1
1
1
0
1
1
0
0
0
1
0
1
0
1
0
0
0
0
1
1
1
1
1
1
0
0
1
0
1
1
1
1
1
0
1
0
0
0
0
0
0
0
0
1
0
es decir, f ilas, columnas y una secuencia de f ilas × columnas valores 0 (blanco) ó 1 (negro).
También dispones de una clase mfset sin rango ni compresión de caminos a la que puedes añadir nuevos métodos si
lo deseas:
c l a s s MFset {
i n t ∗ mfset , n ;
public :
MFset ( i n t N) ;
˜MFset ( ) ;
void merge ( i n t x , i n t y ) ;
int f i n d ( int x ) ;
};
MFset : : MFset ( i n t N) {
n = N ; m f s e t = new in t [ n ] ;
f o r ( i n t i = 0 ; i <n ; i ++) m f s e t [ i ] = i ;
}
Se pide realizar un programa en C++ que reciba el nombre del fichero por la linea de comandos y que:
Muestre por salida estándar el número de regiones negras 4-conectadas. Una región negra 4-conectada es un
grupo de pixels de color negro tal que podemos ir de cualquier pixel a otro en horizontal o vertical por pixels
negros. El ejemplo de la figura tiene 4 componentes.
Salve el mismo fichero guardando cada región negra 4-conectada con un color diferente (los colores son valores
numéricos consecutivos: 1, 2, 3, 4, . . . (el 0 se reserva para el fondo blanco).
Muestre por salida estándar cuántos pixels negros tiene la región negra 4-conectada más grande.
Solución
#include < i o s t r e a m >
#include < f s t r e a m >
#include < c s t d l i b > // para e x i t
using namespace s t d ;
c l a s s MFset {
i n t ∗ mfset , n ;
public :
MFset ( i n t N) ;
˜MFset ( ) ;
void merge ( i n t x , i n t y ) ;
int f i n d ( int x ) ;
void examen ( i n t ∗ ∗ p i x e l s , i n t & n u m r e g i o n e s , i n t & max negro , i n t f i l a s , i n t
columnas ) ;
};
MFset : : MFset ( i n t N) {
n = N ; m f s e t = new in t [ n ] ;
f o r ( i n t i = 0 ; i <n ; i ++) m f s e t [ i ] = i ;
}
MFset : : ˜ MFset ( ) {
delete [ ] m f s e t ;
}
void MFset : : merge ( i n t x , i n t y ) {
m f s e t [ f i n d ( y ) ] = f i n d ( x ) ; // Ponemos y como h i j o de x
}
i n t MFset : : f i n d ( i n t x ) {
while ( m f s e t [ x ] ! = x ) x=m f s e t [ x ] ;
return x ;
}
void MFset : : examen ( i n t ∗ ∗ p i x e l s , i n t & n u m r e g i o n e s , i n t & max negro ,
i n t f i l a s , i n t columnas ) {
n u m r e g i o n e s = 0 ; max negro =0;
i n t f , c , rep , c o n t ;
// c a l c u l a m o s e l numero de r e g i o n e s
f o r ( f = 0 ; f < f i l a s ; f ++)
f o r ( c = 0 ; c<columnas ; c++)
i f ( p i x e l s [ f ] [ c ]==1 && m f s e t [ f ∗ columnas+c]== f ∗ columnas+c ) // r e p r e s e n t a n t e
n u m r e g i o n e s ++;
// c a l c u l a m o s l o s r e p r e s e n t a n t e s
i n t ∗ r e p r e s e n t a n t e s = new in t [ n u m r e g i o n e s ] ;
r e p =0;
f o r ( f = 0 ; f < f i l a s ; f ++)
f o r ( c = 0 ; c<columnas ; c++)
i f ( p i x e l s [ f ] [ c ]==1 && m f s e t [ f ∗ columnas+c]== f ∗ columnas+c ) {
r e p r e s e n t a n t e s [ r e p ]= f ∗ columnas+c ;
r e p++;
}
f o r ( r e p = 0 ; rep<n u m r e g i o n e s ; r e p++){
c o n t =0;
f o r ( f = 0 ; f < f i l a s ; f ++)
f o r ( c = 0 ; c<columnas ; c++)
i f ( p i x e l s [ f ] [ c ]==1 && f i n d ( f ∗ columnas+c )==r e p r e s e n t a n t e s [ r e p ] ) {
c o n t++;
p i x e l s [ f ] [ c ]= r e p + 1 ; // c o l o r e a m o s
}
i f ( c o n t > max negro ) // miramos s i e s l a r e g i o n con mas p i x e l e s
max negro=c o n t ;
}
delete [ ] r e p r e s e n t a n t e s ;
}
i n t main ( i n t argc , char ∗ ∗ argv ) {
i f ( argc != 2) {
c e r r << ”Uso : ” << argv [0] < < ” f i c h e r o ” << e n d l ;
exit (0) ;
}
i f s t r e a m f l e o ( argv [ 1 ] ) ;
if (! f leo ) {
c e r r << ” E r r o r a l a b r i r ” << argv [1] < < e n d l ;
exit (1) ;
}
i n t f i l a s , columnas , ∗ ∗ p i x e l s ;
// suponemos que e l f i c h e r o t i e n e e l f o r m a t o adecuado
f l e o >> f i l a s >> columnas ; // l e e m o s l a s d i m e n s i o n e s
p i x e l s = new in t ∗ [ f i l a s ] ;
f o r ( i n t f = 0 ; f < f i l a s ; f ++)
p i x e l s [ f ] = new in t [ columnas ] ;
f o r ( i n t f = 0 ; f < f i l a s ; f ++) // l e e m o s l o s p i x e l s
f o r ( i n t c = 0 ; c<columnas ; c++)
f l e o >> p i x e l s [ f ] [ c ] ;
f l e o . close () ;
// ahora c a l c u l a m o s l a s componentes 4− c o n e c t a d a s :
MFset m( f i l a s ∗ columnas ) ;
f o r ( i n t f =0; f < f i l a s ; f ++) // procesamos l a s f i l a s
f o r ( i n t c =0; c<columnas ; c++) { // procesamos l a s columnas
i n t pos=f ∗ columnas+c ;
i f ( p i x e l s [ f ] [ c ]==1) { // estamos en un p i x e l n e gr o
// h o r i z o n t a l
i f ( c +1 < columnas && p i x e l s [ f ] [ c +1]==1)
m. merge ( pos , pos +1) ;
// v e r t i c a l
i f ( f +1 < f i l a s && p i x e l s [ f + 1 ] [ c ]==1)
m. merge ( pos , pos+columnas ) ;
}
}
// ahora c a l c u l a m o s l o que nos p i d e n :
i n t n u m r e g i o n e s , max negro ;
m. examen ( p i x e l s , n u m r e g i o n e s , max negro , f i l a s , columnas ) ;
c o u t << ”La imagen t i e n e ” << n u m r e g i o n e s
<< ” r e g i o n e s 4− c o n e c t a d a s ” << e n d l
<< ”La componente 4− c o n e c t a d a más grande t i e n e ”
<< max negro << ” p i x e l s ” << e n d l ;
o f s t r e a m f e s c ( argv [ 1 ] ) ;
f e s c << f i l a s << ’ ’ << columnas << e n d l ;
f o r ( i n t f = 0 ; f < f i l a s ; f ++){
f o r ( i n t c = 0 ; c<columnas ; c++)
f e s c << ’ ’ << p i x e l s [ f ] [ c ] ;
f e s c << e n d l ;
}
f esc . close () ;
return 0 ;
}

Documentos relacionados