Dada una array de N enteros donde N es par. Hay dos tipos de operaciones permitidas en la array.
- Aumenta el valor de cualquier elemento A[i] en 1.
- Si dos elementos adyacentes en la array son números primos consecutivos, elimine ambos elementos. Es decir, A[i] es un número primo y A[i+1] es el siguiente número primo.
La tarea es encontrar el número mínimo de operaciones requeridas para eliminar todos los elementos de la array.
Ejemplos:
Input : arr[] = { 1, 2, 4, 3 } Output : 5 Minimum 5 operation are required. 1. Increase the 2nd element by 1 { 1, 2, 4, 3 } -> { 1, 3, 4, 3 } 2. Increase the 3rd element by 1 { 1, 3, 4, 3 } -> { 1, 3, 5, 3 } 3. Delete the 2nd and 3rd element { 1, 3, 5, 3 } -> { 1, 3 } 4. Increase the 1st element by 1 { 1, 3 } -> { 2, 3 } 5. Delete the 1st and 2nd element { 2, 3 } -> { } Input : arr[] = {10, 12} Output : 3
Para eliminar números, debemos transformar dos números en dos números primos consecutivos. ¿Cómo calcular el costo mínimo de transformar dos números a, b en dos números primos consecutivos, donde el costo es el número de incremento de ambos números?
Usamos criba para precalcular números primos y luego encontramos el primer primo p que no es mayor que a y el primero mayor que p usando una array.
Una vez que hemos calculado dos números primos más cercanos, usamos Programación Dinámica para resolver el problema. Sea dp[i][j] el costo mínimo de limpiar el subarreglo A[i, j]. Si hay dos números en la array, la respuesta es fácil de encontrar. Ahora, para N > 2, pruebe cualquier elemento en la posición k > i como un par para A[i], tal que haya un número par de elementos de A[i, j] entre A[i] y A[k]. Para un k fijo, el costo mínimo de compensación A[i, j], es decir, dp[i][j], es igual a dp[i + 1][k – 1] + dp[k + 1][j] + ( costo de transformar A[i] y A[k] en números primos consecutivos). Podemos calcular la respuesta iterando sobre todos los k posibles.
A continuación se muestra la implementación del enfoque anterior:
C++
// C++ program to count minimum operations // required to remove an array #include<bits/stdc++.h> #define MAX 100005 using namespace std; // Return the cost to convert two numbers into // consecutive prime number. int cost(int a, int b, int prev[], int nxt[]) { int sub = a + b; if (a <= b && prev[b-1] >= a) return nxt[b] + prev[b-1] - a - b; a = max(a, b); a = nxt[a]; b = nxt[a + 1]; return a + b - sub; } // Sieve to store next and previous prime // to a number. void sieve(int prev[], int nxt[]) { int pr[MAX] = { 0 }; pr[1] = 1; for (int i = 2; i < MAX; i++) { if (pr[i]) continue; for (int j = i*2; j < MAX; j += i) pr[j] = 1; } // Computing next prime each number. for (int i = MAX - 1; i; i--) { if (pr[i] == 0) nxt[i] = i; else nxt[i] = nxt[i+1]; } // Computing previous prime each number. for (int i = 1; i < MAX; i++) { if (pr[i] == 0) prev[i] = i; else prev[i] = prev[i-1]; } } // Return the minimum number of operation required. int minOperation(int arr[], int nxt[], int prev[], int n) { int dp[n + 5][n + 5] = { 0 }; // For each index. for (int r = 0; r < n; r++) { // Each subarray. for (int l = r-1; l >= 0; l -= 2) { dp[l][r] = INT_MAX; for (int ad = l; ad < r; ad += 2) dp[l][r] = min(dp[l][r], dp[l][ad] + dp[ad+1][r-1] + cost(arr[ad], arr[r], prev, nxt)); } } return dp[0][n - 1] + n/2; } // Driven Program int main() { int arr[] = { 1, 2, 4, 3 }; int n = sizeof(arr)/sizeof(arr[0]); int nxt[MAX], prev[MAX]; sieve(prev, nxt); cout << minOperation(arr, nxt, prev, n); return 0; }
Java
// Java program to count minimum operations // required to remove an array class GFG { static final int MAX = 100005; // Return the cost to convert two // numbers into consecutive prime number. static int cost(int a, int b, int prev[], int nxt[]) { int sub = a + b; if (a <= b && prev[b - 1] >= a) { return nxt[b] + prev[b - 1] - a - b; } a = Math.max(a, b); a = nxt[a]; b = nxt[a + 1]; return a + b - sub; } // Sieve to store next and previous // prime to a number. static void sieve(int prev[], int nxt[]) { int pr[] = new int[MAX]; pr[1] = 1; for (int i = 2; i < MAX; i++) { if (pr[i] == 1) { continue; } for (int j = i * 2; j < MAX; j += i) { pr[j] = 1; } } // Computing next prime each number. for (int i = MAX - 2; i > 0; i--) { if (pr[i] == 0) { nxt[i] = i; } else { nxt[i] = nxt[i + 1]; } } // Computing previous prime each number. for (int i = 1; i < MAX; i++) { if (pr[i] == 0) { prev[i] = i; } else { prev[i] = prev[i - 1]; } } } // Return the minimum number // of operation required. static int minOperation(int arr[], int nxt[], int prev[], int n) { int dp[][] = new int[n + 5][n + 5]; // For each index. for (int r = 0; r < n; r++) { // Each subarray. for (int l = r - 1; l >= 0; l -= 2) { dp[l][r] = Integer.MAX_VALUE; for (int ad = l; ad < r; ad += 2) { dp[l][r] = Math.min(dp[l][r], dp[l][ad] + dp[ad + 1][r - 1] + cost(arr[ad], arr[r], prev, nxt)); } } } return dp[0][n - 1] + n / 2; } // Driver Code public static void main(String args[]) { int arr[] = {1, 2, 4, 3}; int n = arr.length; int nxt[] = new int[MAX], prev[] = new int[MAX]; sieve(prev, nxt); System.out.println(minOperation(arr, nxt, prev, n)); } } // This code is contributed by 29AjayKumar
Python3
# Python 3 program to count minimum # operations required to remove an array MAX = 100005 INT_MAX = 10000000 # Return the cost to convert two numbers # into consecutive prime number. def cost(a, b, prev, nxt): sub = a + b if (a <= b and prev[b - 1] >= a): return nxt[b] + prev[b - 1] - a - b a = max(a, b) a = nxt[a] b = nxt[a + 1] return a + b - sub # Sieve to store next and previous # prime to a number. def sieve(prev, nxt): pr = [0 for i in range(MAX)] pr[1] = 1 for i in range(1, MAX): if (pr[i]): continue for j in range(i * 2, MAX, i): pr[j] = 1 # Computing next prime each number. for i in range(MAX - 2, -1, -1): if (pr[i] == 0): nxt[i] = i else: nxt[i] = nxt[i + 1] # Computing previous prime each number. for i in range(1, MAX): if (pr[i] == 0): prev[i] = i else: prev[i] = prev[i - 1] # Return the minimum number of # operation required. def minOperation(arr, nxt, prev, n): dp = [[0 for i in range(n + 5)] for i in range(n + 5)] # For each index. for r in range(n): # Each subarray. for l in range(r - 1, -1, -2): dp[l][r] = INT_MAX; for ad in range(l, r, 2): dp[l][r] = min(dp[l][r], dp[l][ad] + dp[ad + 1][r - 1] + cost(arr[ad], arr[r], prev, nxt)) return dp[0][n - 1] + n // 2 # Driver Code arr = [1, 2, 4, 3] n = len(arr) nxt = [0 for i in range(MAX)] prev = [0 for i in range(MAX)] sieve(prev, nxt) print(minOperation(arr, nxt, prev, n)) # This code is contributed by sahishelangia
C#
// C# program to count minimum operations // required to remove an array using System; class GFG { static int MAX = 100005; // Return the cost to convert two // numbers into consecutive prime number. static int cost(int a, int b, int[] prev, int[] nxt) { int sub = a + b; if (a <= b && prev[b - 1] >= a) { return nxt[b] + prev[b - 1] - a - b; } a = Math.Max(a, b); a = nxt[a]; b = nxt[a + 1]; return a + b - sub; } // Sieve to store next and previous // prime to a number. static void sieve(int[] prev, int[] nxt) { int[] pr = new int[MAX]; pr[1] = 1; for (int i = 2; i < MAX; i++) { if (pr[i] == 1) { continue; } for (int j = i * 2; j < MAX; j += i) { pr[j] = 1; } } // Computing next prime each number. for (int i = MAX - 2; i > 0; i--) { if (pr[i] == 0) { nxt[i] = i; } else { nxt[i] = nxt[i + 1]; } } // Computing previous prime each number. for (int i = 1; i < MAX; i++) { if (pr[i] == 0) { prev[i] = i; } else { prev[i] = prev[i - 1]; } } } // Return the minimum number // of operation required. static int minOperation(int[] arr, int[] nxt, int[] prev, int n) { int[,] dp = new int[n + 5, n + 5]; // For each index. for (int r = 0; r < n; r++) { // Each subarray. for (int l = r - 1; l >= 0; l -= 2) { dp[l, r] = Int32.MaxValue; for (int ad = l; ad < r; ad += 2) { dp[l, r] = Math.Min(dp[l, r], dp[l, ad] + dp[ad + 1, r - 1] + cost(arr[ad], arr[r], prev, nxt)); } } } return dp[0, n - 1] + n / 2; } // Driver Code public static void Main() { int[] arr = {1, 2, 4, 3}; int n = arr.Length; int[] nxt = new int[MAX]; int[] prev = new int[MAX]; sieve(prev, nxt); Console.WriteLine(minOperation(arr, nxt, prev, n)); } } // This code is contributed by Mukul Singh
PHP
<?php // PHP program to count minimum operations // required to remove an array $MAX = 100005; // Return the cost to convert two numbers into // consecutive prime number. function cost($a, $b, &$prev, &$nxt) { $sub = $a + $b; if ($a <= $b && $prev[$b-1] >= $a) return $nxt[$b] + $prev[$b-1] - $a - $b; $a = max($a, $b); $a = $nxt[$a]; $b = $nxt[$a + 1]; return $a + $b - $sub; } // Sieve to store next and previous prime // to a number. function sieve(&$prev, &$nxt) { global $MAX; $pr = array_fill(0,$MAX,NULL); $pr[1] = 1; for ($i = 2; $i < $MAX; $i++) { if ($pr[$i]) continue; for ($j = $i*2; $j < $MAX; $j += $i) $pr[$j] = 1; } // Computing next prime each number. for ($i = $MAX - 1; $i; $i--) { if ($pr[$i] == 0) $nxt[$i] = $i; else $nxt[$i] = $nxt[$i+1]; } // Computing previous prime each number. for ($i = 1; $i < $MAX; $i++) { if ($pr[$i] == 0) $prev[$i] = $i; else $prev[$i] = $prev[$i-1]; } } // Return the minimum number of operation required. function minOperation(&$arr, &$nxt, &$prev, $n) { global $MAX; $dp = array_fill(0,($n + 5),array_fill(0,($n + 5),NULL)); // For each index. for ($r = 0; $r < $n; $r++) { // Each subarray. for ($l = $r-1; $l >= 0; $l -= 2) { $dp[$l][$r] = PHP_INT_MAX; for ($ad = $l; $ad < $r; $ad += 2) $dp[$l][$r] = min($dp[$l][$r], $dp[$l][$ad] + $dp[$ad+1][$r-1] + cost($arr[$ad], $arr[$r], $prev, $nxt)); } } return $dp[0][$n - 1] + $n/2; } // Driven Program $arr = array( 1, 2, 4, 3 ); $n = sizeof($arr)/sizeof($arr[0]); $nxt = array_fill(0,$MAX,NULL); $prev = array_fill(0,$MAX,NULL); sieve($prev, $nxt); echo minOperation($arr, $nxt, $prev, $n); return 0; ?>
Javascript
<script> // Javascript program to count minimum operations // required to remove an array let MAX = 100005; // Return the cost to convert two // numbers into consecutive prime number. function cost(a,b,prev,nxt) { let sub = a + b; if (a <= b && prev[b - 1] >= a) { return nxt[b] + prev[b - 1] - a - b; } a = Math.max(a, b); a = nxt[a]; b = nxt[a + 1]; return a + b - sub; } // Sieve to store next and previous // prime to a number. function sieve(prev,nxt) { let pr = new Array(MAX); for(let i=0;i<MAX;i++) { pr[i]=0; } pr[1] = 1; for (let i = 2; i < MAX; i++) { if (pr[i] == 1) { continue; } for (let j = i * 2; j < MAX; j += i) { pr[j] = 1; } } // Computing next prime each number. for (let i = MAX - 2; i > 0; i--) { if (pr[i] == 0) { nxt[i] = i; } else { nxt[i] = nxt[i + 1]; } } // Computing previous prime each number. for (let i = 1; i < MAX; i++) { if (pr[i] == 0) { prev[i] = i; } else { prev[i] = prev[i - 1]; } } } // Return the minimum number // of operation required. function minOperation(arr,nxt,prev,n) { let dp = new Array(n + 5); for(let i=0;i<n+5;i++) { dp[i]=new Array(n+5); for(let j=0;j<n+5;j++) { dp[i][j]=0; } } // For each index. for (let r = 0; r < n; r++) { // Each subarray. for (let l = r - 1; l >= 0; l -= 2) { dp[l][r] = Number.MAX_VALUE; for (let ad = l; ad < r; ad += 2) { dp[l][r] = Math.min(dp[l][r], dp[l][ad] + dp[ad + 1][r - 1] + cost(arr[ad], arr[r], prev, nxt)); } } } return dp[0][n - 1] + n / 2; } // Driver Code let arr=[1, 2, 4, 3]; let n = arr.length; let nxt=new Array(MAX); let prev=new Array(MAX); sieve(prev, nxt); document.write(minOperation(arr, nxt, prev, n)); // This code is contributed by rag2127 </script>
5
Complejidad Temporal: O(N 3 ).
Este artículo es una contribución de Anuj Chauhan . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Publicación traducida automáticamente
Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA