Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Algoritmi - [OII] Numeri antipatici
Forum - Algoritmi - [OII] Numeri antipatici

Avatar
lolgtfo (Normal User)
Newbie


Messaggi: 5
Iscritto: 16/05/2013

Segnala al moderatore
Postato alle 22:08
Giovedì, 16/05/2013
Ciao a tutti!
Ho cercato di risolvere questo problema proposto alle olimpiadi..
http://81.208.32.83:8080/oii/2009/olimpiadiItaliane/numeri ...

Il mio algoritmo funziona per l'input dato come esempio ma va in timeout nei casi del correttore ufficiale, quindi credo che per input grandi vada in crisi e non sia la soluzione adatta ad un problema di questo tipo. :(

Qualcuno ha qualche idea? (E magari consigli su come affrontare la selezione nazionale delle olimpiadi)

PM Quote
Avatar
lillogoal (Member)
Rookie


Messaggi: 28
Iscritto: 26/04/2013

Segnala al moderatore
Postato alle 22:43
Giovedì, 16/05/2013
Devi scrivere uno pseudo codice? o in quale linguaggio?
Secondo me, continua a riguardare gli esercizi delle vecchie olimpiadi e prova a farli :)

PM Quote
Avatar
Phi (Member)
Expert


Messaggi: 241
Iscritto: 30/12/2009

Segnala al moderatore
Postato alle 14:15
Venerdì, 17/05/2013
Si possono usare C, C++ e Pascal sicuramente, poi forse anche altri.

Se posti il codice che hai scritto tu possiamo capire meglio qual è il problema.

Comunque dato che N può essere 1'000'000 dovresti scrivere un algoritmo lineare.
Controlla che il tuo lo sia.
Dovresti cercare di "controllare" un numero solo un numero costante di volte.

Ultima modifica effettuata da Phi il 17/05/2013 alle 14:18
PM Quote
Avatar
lolgtfo (Normal User)
Newbie


Messaggi: 5
Iscritto: 16/05/2013

Segnala al moderatore
Postato alle 18:27
Venerdì, 17/05/2013
Niente, semplicemente il mio algoritmo partiva dal primo elemento del vettore e sommava fin quando non raggiungeva un valore maggiore o uguale al numero antipatico. Nel primo caso non incrementavo il contatore dei casi trovati, nel secondo caso lo incrementavo e continuavo a ciclare gli elementi fin quando erano 0 e incrementando il contatore ogni volta che lo erano. Appena veniva trovato un numero diverso da 0, rifaceva la stessa cosa per il secondo elemento del vettore ecc...
E mi rendo conto che per N grandi è abbastanza lento.. il codice credo di averlo perso :rofl:

PM Quote
Avatar
lolgtfo (Normal User)
Newbie


Messaggi: 5
Iscritto: 16/05/2013

Segnala al moderatore
Postato alle 19:09
Sabato, 18/05/2013
Codice sorgente - presumibilmente C++

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. long int N, M;
  5.  
  6. int main()
  7. {
  8.         ifstream in("input.txt");
  9.         ofstream out("output.txt");
  10.         in>>M>>N;
  11.         long int v[N];
  12.         long int somma=0;
  13.         long int s=0;
  14.         for(int i=0;i<N;i++)
  15.         {
  16.                 in>>v[i];
  17.         }
  18.         int j=0;
  19.         for(int i=0;i<N-1;i++)
  20.         {
  21.                 somma=v[i];
  22.                 j=i+1;
  23.                 if(somma==M) s++;
  24.                 while(somma<=M && j<N)
  25.                 {
  26.                         somma+=v[j];
  27.                         j++;
  28.                         if(somma==M)
  29.                         {
  30.                                 s++;
  31.                         }
  32.                 }
  33.         }
  34.         out<<s;
  35.         in.close();
  36.         out.close();
  37. }



ora mi risolve tutti i casi nel modo corretto.. ma due mi superano il tempo massimo di 1000 ms.

PM Quote
Avatar
Phi (Member)
Expert


Messaggi: 241
Iscritto: 30/12/2009

Segnala al moderatore
Postato alle 12:39
Domenica, 19/05/2013
Considera la complessità del tuo algoritmo ed il massimo valore di N.
I tuoi 2 cicli for e while richiedono circa N^2 operazione.
Dato che N massimo e 1'000'000 il computer richiederà molto più di 1 secondo per farle.

Devi cercare di scrivere(ed è possibile) un algoritmo che abbia complessità O(n).

PM Quote
Avatar
lolgtfo (Normal User)
Newbie


Messaggi: 5
Iscritto: 16/05/2013

Segnala al moderatore
Postato alle 14:16
Domenica, 19/05/2013
Ecco sì.. c'ero arrivato. Ho chiesto proprio per questo :rofl: Non mi viene in mente niente..

PM Quote
Avatar
Phi (Member)
Expert


Messaggi: 241
Iscritto: 30/12/2009

Segnala al moderatore
Postato alle 16:05
Domenica, 19/05/2013
Intanto io considererei a parte il caso in cui il numero antipatico sia 0.
Il questo caso basta che per ogni gruppo di 0 consecutivi aggiungi alla soluzione finale in quanti modi puoi scegliere degli zeri consecutivi. Se per esempio ai 5 zeri consecutivi dei aggiungere 5*6/2=15 alla soluzione.

Se il numero antipatico non è zero io comincerei a leggere l'array che tu hai chiamato v[], tenendo 3 varabili inizio, fine e somma. somma conterrà la somma dei numeri fra v[inizio] e v[fine], continuo ad aumentare fine alzando somma finché questa non superà o eguaglia M. Se M viene eguagliato allora aumento S, altrimenti comincio ad aumentare inizio ed a diminuire somma finché questa non è minore  o eguaglia M. E così via. Così vedi ogni elemento di v[] poche volte(2 o 3).
Attento però non che quando M viene eguagliato non devi aumentare S di 1, ma devi tenere conto di eventuali zeri che circondato il tratto che hai scoperto avere somma M. Quindi devi contare anche gli zeri che precedono(chiamati zp) e seguono(chiamati zs) ed aggiungere ad s (zp+1)(zs+1).

PM Quote
Avatar
lolgtfo (Normal User)
Newbie


Messaggi: 5
Iscritto: 16/05/2013

Segnala al moderatore
Postato alle 9:42
Martedì, 21/05/2013
ok, grazie :)
Dopo provo ad implementarlo..

PM Quote