Eu tenho uma matriz a[n]
. O número n
é inserido por nós. Preciso encontrar o produto mínimo a[i]
e a[j]
se:
1) abs(i - j) > k
2) a[i] * a[j]
é minimizado
Aqui está a minha solução (muito ingênua):
#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;
}
Mas quero saber se existe alguma maneira mais rápida de encontrar um produto mínimo com distância?
c++
algorithm
optimization
minimum
Mouvre
fonte
fonte
std::vector
? @Scheff - a classificação destruiria os relacionamentos originais de "distância".if (i!=j) if (abs(i - j) > k)
pode ser eliminado. Apenas iniciar o ciclo interior em i + k + 1:for (ll j = i + k + 1; j < n; ++j)
. A verificação com tambémfirst
pode ser eliminada semn
for inicializada anteriormente, por exemplo, commn = a[0] * a[k + 1];
. (Talvez,k
deva ser verificadon
inicialmente para fazer essa prova de bala.) Mas ainda é O (N²). Isso deve ser possível mais rápido ...Respostas:
Supondo que haja pelo menos um par de elementos que satisfaça as condições e nenhuma multiplicação de dois elementos nele exceda, isso pode ser feito no
Theta(n-k)
tempo e noTheta(1)
espaço, na pior e na melhor das hipóteses, com algo assim:Isso é ideal em termos de complexidade assintótica de pior caso, tanto no tempo quanto no espaço, porque o produto ideal pode estar
a[0]
com qualquer um dosn-(k+1)
elementos à distância, pelo menosk+1
, portanto, pelo menos,n-(k+1)
números inteiros precisam ser lidos por qualquer algoritmo que resolva o problema.A ideia por trás do algoritmo é a seguinte:
O produto ideal usa dois elementos de
a
, assuma que sãoa[r]
ea[s]
. Sem perda de generalidade, podemos assumir que,s > r
uma vez que o produto é comutativo.Devido à restrição,
abs(s-r) > k
isso implica ques >= k+1
. Agora,s
cada um dos índices pode satisfazer essa condição, portanto, iteramos sobre esses índices. Essa é a iteraçãoi
do código mostrado, mas é alterada pork+1
conveniência (realmente não importa). Para cada iteração, precisamos encontrar o produto ideal envolvendoi+k+1
o maior índice e compará-lo com a melhor estimativa anterior.Os possíveis índices para parear
i+k+1
são todos menores ou iguaisi
devido ao requisito de distância. Também precisaríamos iterar sobre tudo isso, mas isso é desnecessário porque o mínimo dea[i+k+1]*a[j]
excessoj
no fixoi
é igual amin(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j]))
devido à monotonicidade do produto (levando o mínimo em relação àsa[j]
contas de excesso e de mínimo e máximo para as duas possíveis sinaisa[i+k+1]
ou equivalentes as duas direções possíveis da monotonicidade.)Como o conjunto de
a[j]
valores sobre os quais otimizamos aqui é justo{a[0], ..., a[i]}
, que simplesmente cresce em um elemento (a[i]
) em cada iteraçãoi
, podemos simplesmente acompanharmax(a[j])
emin(a[j])
com variáveis únicas atualizando-as sea[i]
for maior ou menor que os valores ideais anteriores. Isso é feito comback_max
eback_min
no exemplo de código.A primeira etapa da iteração (
i=0
) é pulada no loop e executada como inicialização das variáveis.fonte
a[i+k+1]
são o mínimo e o máximo.Não tenho certeza sobre o mais rápido .
Para o problema mais simples sem i <j - k , o produto mínimo está entre os produtos dos pares dos dois menores e maiores elementos.
Portanto, (o seguinte é muito complicado, veja a resposta da noz )
(• rejeite se k ≤ n
• inicialize minProduct para a [0] * a [k + 1])
começando com {} e {a [ j ] | k ≤ j }
min ( upToI ) × min ( beyondIplusK ), min ( upToI ) × max ( beyondIplusK ),
max ( upToI ) × min ( beyondIplusK ) e max ( upToI ) × max ( beyondIplusK )
fonte
minUpto
,maxUpto
,minBeyond
,maxBeyond
(Você pode criar em duas iterações)? Em seguida, na terceira iteração, para cada índice, encontre o mínimo possível de multiplicação.Para "magnitude mínima"
Encontre os 2 elementos "menor magnitude" e depois (depois de encontrar dois zeros ou pesquisar em toda a matriz), multiplique-os.
Para "valor mais baixo" sem a
abs(i - j) > k
peçaExistem 3 possibilidades:
os dois números negativos mais altos (menor magnitude)
os dois números não negativos de menor magnitude (menor magnitude)
o número negativo mais baixo (maior magnitude) e o número não negativo mais alto (maior magnitude)
Você pode procurar todos os 6 valores e descobrir os produtos e qual é o melhor no final.
Contudo; assim que você vê um zero, sabe que não precisa mais saber sobre as duas primeiras possibilidades; e assim que vir um número negativo e um número não negativo, você saberá que só se importa com a terceira possibilidade.
Isso leva a uma máquina de estados finitos com 3 estados - "cuidado com todas as 3 possibilidades", "a resposta é zero, a menos que um número negativo seja visto" e "apenas se preocupa com a última possibilidade". Isso pode ser implementado como um conjunto de 3 loops, onde 2 dos loops saltam para (
goto
) o meio de outro loop quando o estado (da máquina de estados finitos) muda.Especificamente, pode parecer algo vagamente semelhante (não testado):
Para "valor mais baixo" com a
abs(i - j) > k
parteNesse caso, você ainda tem as 3 possibilidades; e poderia fazê-lo funcionar com a mesma abordagem "3 loops com máquina de estados finitos", mas fica muito confuso / feio. Nesse caso, é provável que uma alternativa melhor faça uma varredura prévia da matriz para determinar se há zeros e se todos são negativos ou positivos; para que, após a pré-digitalização, você saiba que a resposta é zero ou selecione um loop projetado apenas para a possibilidade específica.
fonte