mi sembra che sei vicino ...
Stai prendendo il min() di due termini, ognuno dei quali è min[i - p] + 1
, dove p è 1 o qualche altra piazza < i.
Per risolvere questo problema, basta prendere il min() di min[i - p] + 1
sopra tutti p (dove p è un quadrato < i).
Questo sarebbe a modo corretto. Potrebbe esserci un modo più veloce.
Inoltre, potrebbe facilitare la leggibilità se si danno nomi min[]
e min()
diversi. :-)
P.S. l'approccio di cui sopra richiede che si memoize min[]
, esplicitamente o come parte del framework DP. Altrimenti, la complessità dell'algoritmo, dovuto alla ricorsione, sarebbe qualcosa come O (sqrt (n)!): -p anche se il caso medio potrebbe essere molto meglio.
P.P.S. Vedi @ Risposta di Nikita per una buona implementazione. A cui aggiungerei le seguenti ottimizzazioni ... (Non sto snellando la sua implementazione - lo ha presentato come semplice.)
- Verificare se n è un quadrato perfetto, prima di entrare nel ciclo esterno: se è così, min [n] = 1 e abbiamo finito.
- Verificare se è un quadrato perfetto prima di entrare nel ciclo interno: in tal caso, min [i] = 1 e saltare il ciclo interno.
- Break out del loop interno se min [i] è stato impostato su 2, perché non migliorerà (se fosse possibile farlo con un quadrato, non avremmo mai inserito il ciclo interno, grazie al precedente ottimizzazione).
- Mi chiedo se la condizione di terminazione sul loop interno possa essere modificata per ridurre il numero di iterazioni, ad es.
j*j*2 <= i
o anche j*j*4 <= i
. Penso di sì ma non ho la testa completamente intorno.
Per i grandi, sarebbe più veloce calcolare un limite per j prima del ciclo interno e confrontare j direttamente con esso per la condizione di terminazione del loop, piuttosto che squadrare j su ogni iterazione del ciclo interno. Per esempio.
float sqrti = Math.sqrt(i);
for (int j = 1; j <= sqrti; ++j) {
D'altra parte, è necessario j^2 per il passo di ricorsione in ogni caso, così finché si memorizza, si potrebbe anche usarlo.
+1 per un'implementazione. L'OP potrebbe voler saltare il ciclo interno nei casi in cui io sia un quadrato perfetto, in linea con la sua definizione di DP. Anche se potrebbe volerci più tempo per controllare se sono un quadrato, che passare attraverso il loop! – LarsH
Forse vuoi correggere un refuso: Nella formula dopo "scriverà condizione come", l'espressione min (...) manca un secondo argomento "min [i]" - come nel frammento di codice. (Ho provato ad aggiornare la tua risposta, ma la mia modifica è stata rifiutata: "Questa modifica aveva lo scopo di indirizzare l'autore del post e non ha senso come modifica. Dovrebbe essere stato scritto come commento o risposta"). – JimiLoe