Tengo una matriz a[n]
. El número n
lo ingresamos nosotros. Necesito encontrar el producto mínimo de a[i]
y a[j]
si:
1) abs(i - j) > k
2) a[i] * a[j]
se minimiza
Aquí está mi solución (muy ingenua):
#include <iostream>
using namespace std;
#define ll long long
int main() {
ll n,k; cin >> n >> k;
ll a[n]; for(ll i=0;i<n;i++) cin >> a[i];
ll mn; bool first = true;
for(ll i=0;i<n;i++) {
for(ll j=0;j<n;j++) {
if(i!=j)
if(abs(i-j) > k) {
if(first) {
mn = a[i]*a[j];
first = false;
} else if(a[i]*a[j] < mn) mn = a[i]*a[j];
}
}
}
cout << mn << endl;
}
¿Pero quiero saber si hay alguna forma más rápida de encontrar un producto mínimo con distancia?
c++
algorithm
optimization
minimum
Mouvre
fuente
fuente
std::vector
? @Scheff: la clasificación destruiría las relaciones originales de "distancia".if (i!=j) if (abs(i - j) > k)
puede ser eliminado. Sólo empezar el bucle interior en i + k + 1:for (ll j = i + k + 1; j < n; ++j)
. La verificación con tambiénfirst
se puede eliminar simn
se inicializa antes, por ejemplo, conmn = a[0] * a[k + 1];
. (Tal vez,k
debería verificarsen
inicialmente para hacer esto a prueba de balas). Pero sigue siendo O (N²). Esto debe ser factible más rápido ...Respuestas:
Suponiendo que haya al menos un par de elementos que satisfagan las condiciones y que no se desborde la multiplicación de dos elementos, esto puede hacerse en el
Theta(n-k)
tiempo y elTheta(1)
espacio en el peor y el mejor de los casos, con algo como esto:Esto es óptimo en términos de la complejidad asintótica del peor de los casos, tanto para el tiempo como para el espacio, porque el producto óptimo puede estar
a[0]
con cualquiera de losn-(k+1)
elementos en la distancia, al menosk+1
, por lon-(k+1)
que cualquier algoritmo que resuelva el problema debe leer al menos los enteros.La idea detrás del algoritmo es la siguiente:
El producto óptimo utiliza dos elementos de
a
, suponga que estos sona[r]
ya[s]
. Sin pérdida de generalidad podemos suponer ques > r
dado que el producto es conmutativo.Debido a la restricción,
abs(s-r) > k
esto implica ques >= k+1
. Ahoras
podría ser cada uno de los índices que satisfagan esta condición, por lo que iteramos sobre estos índices. Esa es la iteracióni
en el código que se muestra, pero se cambia pork+1
conveniencia (realmente no importa). Para cada iteración, necesitamos encontrar el producto óptimo que incluya eli+k+1
mayor índice y compararlo con la mejor estimación anterior.Los índices posibles para emparejar
i+k+1
son todos índices menores o igualesi
debido al requisito de distancia. Tendríamos que repetir todo esto también, pero eso es innecesario porque el mínimo dea[i+k+1]*a[j]
overj
en fijoi
es igual amin(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))
debido a la monotonicidad del producto (tomando el mínimo con respecto al mínimo y al máximo sobrea[j]
cuentas para los dos posibles signos de,a[i+k+1]
o equivalentemente, las dos posibles direcciones de monotonicidad.)Dado que el conjunto de
a[j]
valores sobre el que optimizamos aquí es justo{a[0], ..., a[i]}
, que simplemente crece por un elemento (a[i]
) en cada iteración dei
, simplemente podemos realizar un seguimiento demax(a[j])
ymin(a[j])
con variables individuales actualizándolas sia[i]
es mayor o menor que los valores óptimos anteriores. Esto se hace conback_max
yback_min
en el ejemplo de código.El primer paso de la iteración (
i=0
) se omite en el bucle y, en su lugar, se realiza como inicialización de las variables.fuente
a[i+k+1]
son el mínimo y el máximo.No estoy seguro sobre lo más rápido .
Para el problema más simple sin i <j - k , el producto mínimo se encuentra entre los productos de pares de los dos elementos más pequeños y más grandes.
Entonces, (lo siguiente es demasiado complicado, ver la respuesta de nuez )
(• rechazar si k ≤ n
• inicializar minProduct a a [0] * a [k + 1])
comenzando con {} y {a [ j ] | k ≤ j }
min ( upToI ) × min ( beyondIplusK ), min ( upToI ) × max ( beyondIplusK ),
max ( upToI ) × min ( beyondIplusK ) y max ( upToI ) × max ( beyondIplusK )
fuente
minUpto
,maxUpto
,minBeyond
,maxBeyond
(Se puede crear en dos iteraciones)? Luego, en la tercera iteración, para cada índice, encuentre la multiplicación mínima posible.Para "magnitud mínima"
Encuentre los 2 elementos de "magnitud más pequeña" y luego (después de haber encontrado dos ceros o buscado en toda la matriz), multiplíquelos.
Para el "valor más bajo" sin la
abs(i - j) > k
parteHay 3 posibilidades:
los dos números negativos más altos (magnitud más pequeña)
los dos números no negativos más bajos (magnitud más pequeña)
el número negativo más bajo (magnitud más grande) y el número no negativo más alto (magnitud más grande)
Puede buscar los 6 valores y descubrir los productos y cuál es el mejor al final.
Sin embargo; tan pronto como vea un cero, sabe que no necesita saber más acerca de las 2 primeras posibilidades; y tan pronto como veas un número negativo y uno no negativo, sabrás que solo te importa la tercera posibilidad.
Esto lleva a una máquina de estados finitos con 3 estados: "preocuparse por las 3 posibilidades", "la respuesta es cero a menos que se vea un número negativo" y "solo preocuparse por la última posibilidad". Esto se puede implementar como un conjunto de 3 bucles, donde 2 de los bucles saltan a (
goto
) el centro de otro bucle cuando cambia el estado (de la máquina de estados finitos).Específicamente, podría parecerse a algo vagamente (no probado):
Para el "valor más bajo" con la
abs(i - j) > k
parteEn este caso todavía tienes las 3 posibilidades; y podría hacerlo funcionar con el mismo enfoque de "3 bucles con máquina de estados finitos", pero se vuelve demasiado desordenado / feo. Para este caso, es probable que una mejor alternativa escanee previamente la matriz para determinar si hay ceros y si todos son negativos o todos positivos; para que después de la exploración previa pueda saber si la respuesta es cero o seleccionar un bucle diseñado solo para la posibilidad específica.
fuente