Autor
|
Tema: Problema en c++ - Números k-emparejados (Leído 2,671 veces)
|
MariCarmeniii
Desconectado
Mensajes: 3
|
Algoritmo iterativo. El problema: Dos números se llaman k-emparejadoscuando cuando el valor absoluto de su diferencia es exactamente k(es decir, u y v están k-emparejados cuando |u–v| = k ). Por ejemplo, 7 y 14 están 7-emparejados. Observa que todo número está 0-emparejado consigo mismo. Diseña un algoritmo eficiente que, dado un vector estrictamente creciente de enteros int a[n] (n>=0) y un número k>=0, determine el número de parejas de números en a que están k-emparejados. La entrada termina con una línea que empieza por -1. Cada vez que lee un caso de prueba, el programa invoca a una función num_k_emparejados que determina el número de parejas de números k-emparejados, y escribe dicho número por la salida estándar. A continuación, se muestra un ejemplo de entrada procesable por este programa, y de salida producida (suponiendo una implementación adecuada de num_k_emparejados): Entrada Salida 5 3 2 1 4 5 6 8 1 4 2 3 1 4 5 6 3 0 1 2 3 -1 Esqueleto de lo que llevo: #include <algorithm> #include <iostream>
using namespace std;
/*
PRECONDICION DE LA FUNCION:
*/ unsigned int num_k_emparejados(int v[], unsigned int n, unsigned int k); /* POSTCONDICION DE LA FUNCION:
*/
unsigned int num_k_emparejados(int v[], unsigned int n, unsigned int k) { /* CUERPO DE LA FUNCION */
}
/* Complejidad: orden de complejidad del algoritmo:
*/
bool procesa_caso() { int v[100]; int n, k; cin >> n; if (n != -1) { cin >> k; for (int i = 0; i < n; i++) { cin >> v[i]; } cout << num_k_emparejados(v, n, k) << endl; return true; } else { return false; } }
int main() { while (procesa_caso()); }
Si me podéis ayudar con la función unsigned int num_k_emparejados lo agradecería.
|
|
« Última modificación: 21 Octubre 2019, 14:46 pm por MariCarmeniii »
|
En línea
|
|
|
|
|
MariCarmeniii
Desconectado
Mensajes: 3
|
Sii muchas gracias, lo he estado ojeando antes de subir el tema pero no me sirve porque no es en modo iterativo pero muchas gracias por responder =)
|
|
|
En línea
|
|
|
|
K-YreX
|
El modo de resolución a mí sí me parece que es iterativo. Si no es lo que buscas añade un poco más de código para ver qué es lo que quieres implementar.
|
|
|
En línea
|
cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
|
|
|
MariCarmeniii
Desconectado
Mensajes: 3
|
Hola chic@s, os dejo la solución del problema: #include <algorithm> #include <iostream>
using namespace std;
/*
PRECONDICION DE LA FUNCION: ---Escribe aqu� la precondici�n de la funci�n.
0<=n<=tam(v) && crec(v,n) */ unsigned int num_k_emparejados(int v[], unsigned int n, unsigned int k); /* POSTCONDICION DE LA FUNCION: ---Escribe aqu� la poscondici�n de la funci�n. Para refirte ---al valor devuelto por la funci�n, utiliza la pseudo-variable ---'res' (1) Definiciones auxiliares (si procede): crec(v,n) = PARATODO i: 0<=i<n-1: v[i] < v[i+1] num_k_emp(v,n,k) = #i,j:0<=i<=j<n:|v[i]-v[j]|=k
(2) Postcondici�n res = num_k_emp(v,n,k)
*/ /* DISE�O DEL ALGORITMO: --- Detalla aqu� el proceso seguido para dise�ar el --- algoritmo PASO 1. Variables v,n,res,i,j PASO 2. Invariante (1) res = num_k_emp_hasta(v,n,k,i) donde num_k_emp_hasta(v,n,k,t) = #u,w:0<=u<=w<n && u < t:|v[u]-v[w]|=k (2) 0 <= i <= j <= n (3) no_k_emp(v,k,i,j) donde no_k_emp(v,k,i,j) = PARATODO u,w: i<=u<=w<j: |v[u]-v[w]|<k PASO 3. Inicializaci�n: i=0 j=0 res = num_k_emp_hasta(v,n,k,j) = num_k_emp_hasta(v,n,k,0) = (#u,w:0<=u<=w<n && u < 0:|v[u]-v[w]|=k) = (#u,w:false:|v[u]-v[w]|=k) = 0 PASO 4: Continuaci�n y finalizaci�n: j != n * Si j = n, entonces: (1) El invariante asegura que res = num_k_emp_hasta(v,n,k,i) (2) Tambi�n asegura que no_k_emp(v,k,i,j) (3) Por tanto, res = num_k_emp_hasta(v,n,k,j) (4) Pero,como j=n, entonces res = num_k_emp_hasta(v,n,k,n) PASO 5: Cuerpo del bucle. Como 0 <= i <= j <= n y adem�s j != n (por la condici�n del bucle), podemos asegurar que 0<=i<n y 0<=j < n. Por tanto, tanto v[i] como v[j] tienen sentido. * Si |v[i]-v[j]|<k: (1) Incrementamos j, para hacer la diferencia m�s grande. Esto afecta a: (1) 0 <= i <= j <= n. Pero, como 0 <= j <n antes del incremento, despu�s de incrementar j el t�rmino sigue siendo v�lido. (2) no_k_emp(v,k,i,j). Pero, como |v[i]-v[j]|<k, y como v es estrictamente creciente, entonces el t�rmino se preserva. * Si |v[i]-v[j]|>k: Incrementamos i. Esto afecta a: (1) 0 <= i <= j <= n. Pero como, antes de incrementar i, 0 <= i <=j, y |v[i]-v[j]|>k asegura que i < j (por ser v estrictamente creciente), el t�rmino se preserva tras incrementar i. (2) res = num_k_emp_hasta(v,n,k,i). Pero, como se cumpl�a: (i) no_k_emp(v,k,i,j); (ii) |v[i]-v[j]|>k; (iii) el vector es estrictamente creciente, por lo que, al ser |v[i]-v[j]|>k, no podemos encontrar un w > j, tal que |v[i]-v[w]|=k, tras incrementar i podemos asegurar que el t�rmino contin�a verific�ndose. * Si |v[i]-v[j]|=k. En este caso: (1) Incrementamos 'res', al haber encontrado una nueva k-pareja. (2) Pero esto afecta a res = num_k_emp_hasta(v,n,k,i). Como el vector es estrictamente creciente, y como |v[i]-v[j]|=k, no habr� w > j, tal que |v[i]-v[w]|=k. Por tanto, para reestablecer el t�rmino basta incrementar i. Pero esto afecta: (2.1) A no_k_emp(v,k,i,j). Pero como, antes de incrementar i, se cumple para v[i..j), podemos asegurar que se cumpl�a tambi�n para v(i..j). Por tanto, tras incrementar i el t�rmino sigue siendo v�lido. (2.2) A 0 <= i <= j <= n. Si, antes del incremento, i=j, el t�rmino se viola. Para evitarlo, en este caso debemos incrementar j. Pero entonces, puede verse afectado: (2.1.1) 0 <= i <= j <= n. Pero este t�rmino sigue cumpli�ndose, ya que, tras incrementar j, i=j (al serlo antes de incrementar i y j), y adem�s 0<=j<n. (2.1.2) no_k_emp(v,k,i,j). Pero, como i=j, esto es no_k_emp(v,k,i,i) = PARATODO u,w: i<=u<=w<i: |v[u]-v[w]|<k = true. PASO 6: Terminaci�n 2n - (i+j) es una expresi�n de cota. * Como en cada iteraci�n se incrementa i o j, la expresi�n disminuye. * Adem�s, podemos comprobar que 2n - (i+j) >= 0 es un invariante del bucle: - Al inicializar i=j=0, 2n - (i+j) = 2n >= 0. - Supongamos que 2n - (i+j) >= 0 se cumple al entrar en el cuerpo del bucle. Como i < n y j <n, 2n - (i+j) no va a ser m�s peque�a que 2n - ((n-1)+(n-1)) = 2n - 2n + 2 = 2. Por tanto, en el caso m�s extremo en el que incrementamos tanto i como j, a la salida del bucle 2n - (i+j) no va a ser m�s peque�a que 0. */
unsigned int num_k_emparejados(int v[], unsigned int n, unsigned int k) { int i=0; int j=0; int res=0; while (j!=n) { int d = v[j]-v[i]; if (d < k) { j++; } else { if (d == k) { res++; if (i == j) j++; } i++; } } return res; }
/* Complejidad: Determina justificadamente el orden de complejidad de este algoritmo: * Con la expresi�n de cota hemos visto que el bucle no da m�s de 2n vueltas. Como el cuerpo se ejecuta en tiempo constante, la complejidad es lineal ( O(n) ).
*/
bool procesa_caso() { int v[100]; int n, k; cin >> n; if (n != -1) { cin >> k; for (int i = 0; i < n; i++) { cin >> v[i]; } cout << num_k_emparejados(v, n, k) << endl; return true; } else { return false; } }
int main() { while (procesa_caso()); }
Por si os interesa, saludos.
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Problema con generador de numeros
Programación Visual Basic
|
bautistasbr
|
6
|
2,491
|
11 Julio 2006, 22:41 pm
por bautistasbr
|
|
|
[Problema] Programa para averiguar números pares entre 2 números
Programación Visual Basic
|
Dreamaker
|
3
|
5,846
|
21 Mayo 2010, 23:45 pm
por Shell Root
|
|
|
Problema con números largos
Programación C/C++
|
DickGumshoe
|
6
|
3,947
|
5 Julio 2012, 12:28 pm
por DickGumshoe
|
|
|
problema l requerir números
« 1 2 »
Programación C/C++
|
7hongo7
|
13
|
6,411
|
20 Febrero 2013, 18:49 pm
por 7hongo7
|
|
|
Problema k-paired (k-emparejados) en O(N)
« 1 2 »
Programación C/C++
|
dijsktra
|
18
|
6,356
|
27 Septiembre 2019, 01:06 am
por RayR
|
|