Segundo parcial de EDA Facultad de Informática de Valencia 10 de junio de 2009 – Duración 2 horas No olvides poner el nombre. No utilices lápiz ni tinta roja. Se piden siempre soluciones eficientes. Pregunta 1 (1.5 puntos) Dada la siguiente implementación de un árbol representado mediante nodos con un puntero al hijo izquierdo y otro al hermano derecho: struct nodoArbol { int v a l o r ; nodoArbol ∗ h i j o , ∗ hermano ; }; c l a s s Arbol { nodoArbol ∗ r a i z ; public : // c o n t r u c t o r , metodos i n s e r t a r , . . . i n t c o n t a r H o j a s ( ) const ; // EJERCICIO DEL EXAMEN }; Se pide implementar el método contarHojas que cuente el número de hojas del árbol. Nota: puedes añadir nuevos métodos si lo consideras conveniente, pero no puedes añadir nuevos atributos. Solución: i n t nodoArbol : : c o n t a r H o j a s ( ) const { i f ( h i j o ==0) // s o y hoja , no t e n g o h i j o s return 1 ; // no s o y hoja , c u e n t o l a s h o j a s de mis h i j o s i n t c o n t =0; f o r ( const nodoArbol ∗ r=h i j o ; r ! = 0 ; r=r−>hermano ) c o n t += r−>c o n t a r H o j a s ( ) ; return c o n t ; } i n t Arbol : : c o n t a r H o j a s ( ) const { return ( r a i z ) ? r a i z −>c o n t a r H o j a s ( ) : 0 ; } Pregunta 2 (2 puntos) Dada la siguiente implementación de un grafo: struct edge { int d e s t ; // v e r t i c e d e s t i n o edge ∗ next ; // s i g u i e n t e en l a l i s t a edge ( i n t d , edge ∗n ) { d e s t=d ; next=n ; } }; c l a s s graph { i n t nVert ; // numero de v e r t i c e s edge ∗∗L ; // l i s t a de a d y a c e n c i a public : graph ( i n t nv ) ; ˜ graph ( ) ; graph ∗ c o n D o b l e D i r e c c i o n ( ) const ; // EJERCICIO DE EXAMEN }; Implementa el método conDobleDireccion que, con coste espacial y temporal O(|V |+|A|), devuelve un nuevo grafo que tiene únicamente las aristas (u, v) del grafo original tales que tanto (u, v) como (v, u) estén en el grafo. Justifica adecuadamente el coste espacial y temporal de tu algoritmo. MUY IMPORTANTE: Se considerará incorrecta una solución que, para grafos dispersos, tenga un coste espacial o temporal O(|V |2 ). Solución: graph ∗ graph : : c o n D o b l e D i r e c c i o n ( ) const { // creamos un v e c t o r de t a l l a nVert i n t ∗ usado = new i n t [ nVert ] ; // creamos g r a f o a u x i l i a r con e l r e v e r s o e i n i c i a l i z a m o s usado : graph ∗ r e v e r s o = new graph ( nVert ) ; f o r ( i n t i =0; i <nVert ; ++i ) { usado [ i ] = −1; f o r ( const edge ∗ r=L [ i ] ; r ! = 0 ; r=r−>next ) r e v e r s o −>L [ r−>d e s t ] = new edge ( i , r e v e r s o −>L [ r−>d e s t ] ) ; } // creamos e l g r a f o r e s u l t a d o : graph ∗ r e s u l t a d o = new graph ( nVert ) ; // r e c o r r e m o s e l p r o p i o g r a f o y e l r e v e r s o a l a v e z f o r ( i n t i =0; i <nVert ; ++i ) { f o r ( const edge ∗ r=L [ i ] ; r ! = 0 ; r=r−>next ) usado [ r−>d e s t ] = i ; // marcamos como v i s t o en i t e r a c i o n i f o r ( const edge ∗ r=r e v e r s o −>L [ i ] ; r ! = 0 ; r=r−>next ) i f ( usado [ r−>d e s t ] == i ) r e s u l t a d o −>L [ i ] = new edge ( r−>d e s t , r e s u l t a d o −>L [ i ] ) ; } // l i b e r a m o s memoria : delete [ ] usado ; delete r e v e r s o ; // d e v o l v e m o s l o que nos p i d e n : ) return r e s u l t a d o ; } Pregunta 3 (3 puntos) La compañı́a de televisión por cable Clark Cable decide instalar su red en la provincia de Valencia. Para conectar las N ciudades más importantes ha elaborado una matriz de talla N × N con las distancias entre las ciudades. Sabemos que el coste de un cableado entre dos ciudades varı́a con la distancia de la manera siguiente: 100 euros/metro en distancias d ≤ 1000 metros, 75 euros/metro en distancias d > 1000 metros, Queremos calcular la longitud del cableado más barato. Para ello, implementa la función: double long itudCab leadoMa sBarat o ( double m[N ] [ N ] ) ; Solución: double p r e c i o ( double metros ) { double pormetro = ( metros <= 1 0 0 0 ) ? 100 : 7 5 ; return metros ∗ pormetro ; } double long itudCab leadoMa sBarat o ( double m[N ] [ N ] ) { // Prim double D[N ] ; // menores d i s t a n c i a s int P [N ] ; // p r e d e c e s o r bool S [N ] ; // s e l e c c i o n a d o double r e s u l t a d o = 0 ; // r e s u l t a d o a c a l c u l a r f o r ( i n t i =0; i <N;++ i ) { // i n i c i a l i z a m o s P [ i ] = 0 ; // p a r t i m o s d e l v é r t i c e 0 D[ i ] = m[ 0 ] [ i ] ; S [ i ] = false ; } S [ 0 ] = true ; // p a r t i m o s d e l v é r t i c e 0 f o r ( i n t i t e r =0; i t e r <N−1; ++i t e r ) { // t a n t a s como número de a r i s t a s i n t s e l e c = −1; double m i n d i s t = i n f i n i t y ; f o r ( i n t i =0; i <N;++ i ) i f ( ! S [ i ] && D[ i ]< m i n d i s t ) { m i n d i s t=D[ i ] ; s e l e c=i ; } S [ s e l e c ] = true ; r e s u l t a d o += m[ s e l e c ] [ P [ s e l e c ] ] ; f o r ( i n t i =0; i <N;++ i ) { double pvp = p r e c i o (m[ s e l e c ] [ i ] ) ; i f ( ! S [ i ] && pvp<D[ i ] ) { D[ i ]=pvp ; P [ i ]= s e l e c ; } } } return r e s u l t a d o ; } Pregunta 4 (3.5 puntos) Dado un grafo, nos gustarı́a encontrar caminos de longitud N que cumplan las siguientes condiciones: Los vértices tiene guardado un premio que nos llevamos al visitar el vértice. Si visitamos un vértice más de una vez, sólo nos dan el premio la primera vez. Las aristas tienen asociado un peaje a pagar para cruzarlas. Como no nos fian, no podremos cruzar una arista si tenemos menos dinero que el precio del peaje. Implementa un algoritmo de búsqueda con retroceso o backtracking para calcular todos los caminos válidos. Por cada camino encontrado se deberá llamar al método processSolution pasándole la solución encontrada. Recuerda que la longitud es el número de aristas utilizadas. struct edge { int d e s t ; // d e s t i n o int t o l l ; // p e a j e edge ∗ next ; // s i g u i e n t e en l a l i s t a }; c l a s s graph { i n t nVert ; // numero de v e r t i c e s edge ∗∗L ; // l i s t a de a d y a c e n c i a i n t ∗ reward ; // recompensa que r e c i b i m o s en cada v e r t i c e public : // métodos v a r i o s para c o n s t r u i r e l g r a f o // NO IMPLEMENTAR ESTE METODO, SOLO UTILIZARLO void p r o c e s s S o l u t i o n ( i n t N, i n t s o l [ ] ) ; // EJERCICIO DE EXAMEN void f i n d V a l i d P a t h s ( i n t int int int N, // s o l S i z e , // sol [] , // mymoney ) ; // l o n g i t u d d e l camino p e d i d o l o n g i t u d de l a s o l u c i o n en c u r s o vector solucion d i n e r o que t e n g o }; i n t main ( ) { . . . // l e e r número de v é r t i c e s , N, e t c . graph g ( numVert ) ; . . . // i n t r o d u c i r l a s a r i s t a s y o t r o s v a l o r e s d e l g r a f o i n t ∗ s o l = new i n t [N ] ; g . f i n d V a l i d P a t h s ( lenPath , 0 , s o l , 0 ) ; // empezamos con 0 e u r o s : ’ ( delete [ ] s o l ; ... } Solución: void graph : : f i n d V a l i d P a t h s ( i n t N, // l o n g i t u d camino p e d i d o int s o l S i z e , // n . v e r t i c e s s o l en c u r s o int s o l [ ] , // v e c t o r s o l u c i o n i n t mymoney ) { // d i n e r o que t e n g o i f ( s o l S i z e −1 == N) { // e s t e r m i n a l : p r o c e s s S o l u t i o n (N, s o l ) ; } e l s e { // no e s t e r m i n a l , r a m i f i c a m o s i f ( s o l S i z e == 0 ) { // empezar o c o n t i n u a r ? f o r ( i n t i =0; i <nVert;++ i ) { // podemos empezar sol [0] = i ; // en c u a l q u i e r v e r t i c e f i n d V a l i d P a t h s (N, 1 , s o l , mymoney ) ; } } e l s e { // c o n t i n u a r d e s d e e l ú l t i m o v é r t i c e int u l t i m o V e r t i c e = s o l [ solSize −1]; int d i n e r o V e r t i c e = reward [ u l t i m o V e r t i c e ] ; reward [ u l t i m o V e r t i c e ] = 0 ; // no me puedo v o l v e r mymoney += d i n e r o V e r t i c e ; // a l l e v a r e l premio f o r ( edge ∗ r = L [ u l t i m o V e r t i c e ] ; r ! = 0 ; r=r−>next ) { i f ( mymoney >= r−> t o l l ) { // s i puedo p a ga r e l p e a j e s o l [ s o l S i z e ] = r−>d e s t ; f i n d V a l i d P a t h s (N, s o l S i z e +1,mymoney − r−> t o l l ) ; } } reward [ u l t i m o V e r t i c e ] = d i n e r o V e r t i c e ; // d e s h a g o l o s cambios } } }