Operaciones mínimas requeridas para eliminar una array

Dada una array de N enteros donde N es par. Hay dos tipos de operaciones permitidas en la array. 

  1. Aumenta el valor de cualquier elemento A[i] en 1.
  2. 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>
Producción

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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *