Przyspieszenie algorytmu zadania na OIG

0

Witam, przygotowuję się do Olimpiady Informatycznej Gimnazjalistów i aktualnie piszę program do następującego programu - https://drive.google.com/file/d/0B5WbnRptdfRAcXpUWExleDlVZDg/view?usp=sharing. Napisałem go i działa popranie, lecz za wolno (gdybym go zgłosił to bym dostał ledwo 50% pkt z powodu wolnego działania), oto jego kod:

#include <iostream>
using namespace std;
int main()
{
    //DANE
    int N, S;
    cin >> N >> S;
    
    int O[ N - 1 ], P;
    for( int i = 0; i < N - 1; i++ ) cin >> O[ i ];
    
    cin >> P;
    int AB[ 2 ][ P ], temp = 0, counter = 0;
    for( int i = 0; i < P; i++ ) {
        cin >> AB[ 0 ][ i ] >> AB[ 1 ][ i ];
    }
    
    for( int i = 0; i < P; i++ ) {
        //Jeśli szukamy ilość skoków z bliższego kamienia do dalszego
        if( AB[ 0 ][ i ] < AB[ 1 ][ i ] ) {
            for( int j = AB[ 0 ][ i ]; j < AB[ 1 ][ i ]; j++ ) {
                temp += O[ j - 1 ];
                if( S < temp ) {
                    counter++;
                    temp = 0;
                    j--;
                    continue; }
                if( S == temp ) {
                    counter++;
                    temp = 0; }
            }
            if( temp > 0 ) { counter++; }
            cout << counter << endl;
            counter = 0;
            temp = 0;
            continue;
        } else {
            //Jeśli szukamy ilość skoków z dalszego kamienia do bliższego
            for( int j = AB[ 0 ][ i ]; j > AB[ 1 ][ i ]; j-- ) {
                temp += O[ j - 2 ];
                if( S < temp ) {
                    counter++;
                    temp = 0;
                    j++;
                    continue; }
                if( S == temp ) {
                    counter++;
                    temp = 0; }
                
            }
            if( temp > 0 ) { counter++; }
            cout << counter << endl;
            counter = 0;
            temp = 0;
            continue; }
        //Jeśli mamy skakać z takiego samego kamienia na taki sam
        if( AB[ 0 ][ i ] == AB[ 1 ][ i ] ) { cout << "0" << endl; }
    }
    return 0;
} 

I tu rodzi się moje pytanie - jak go przyspieszyć?

0

@Endrju W Code::Blocks wszystko jest OK

3

Zacznij od napisania tego kodu w wersji dla ludzi. Na przykład poprzez nazywanie zmiennych po ludzku.
Twój problem polega na tym że nie patrzysz na to jakie są zakresy danych. Zauważ że N ma taki sam zakres jak P! To oznacza że ktoś może N razy kazać ci policzyć odległość od początku do końca (N) czyli pesymistycznie N2. Ja bym podszedł do tego tablicując wyniki pośrednie. Zauważ że twój problem ma własność optymalnej podstruktury więc nadaje się na algorytm dynamiczny.
Bo łatwo zaobserwować że jeśli wiem w ilu najmniej skokach mogę pokonać dystans między A i B (i ile "wolnego" zostało mi z ostatniego skoku) to moge od razu powiedzieć w ilu skokach mogę pokonać dystans między A i B+1. Może więc warto policzyć to zawczasu a potem tylko zwracać odpowiedzi?
Oczywiście musisz to policzyć z obu stron, tzn wszystkie skoki od początku do każdego kolejnego oraz od końca do każdego kolejnego. Polecam zastanowić się, jeśli wiesz ile skoków potrzeba pomiędzy A i C oraz pomiędzy D i B oraz pomiędzy A i D, jak policzyć skoki pomiędzy B i C.
W ten sposób uzyskujesz algorytm pesymistycznie liniowy a nie kwadratowy.

0

Omówienie zadania na yt

1 użytkowników online, w tym zalogowanych: 0, gości: 1