Problema semina

Buonasera a tutti,
stavo cercando di risolvere il problema Semina (ABC 2014).
In locale sembra funzionare alla perfezione ma ogni volta che provo a sottomettere la mia soluzione ottengo 0/100.
Non capisco cosa mi sfugga, qualcuno riesce a spiegarmi il problema?

#include <cstdio>
#include <cassert>
#include <algorithm>

using namespace std;

constexpr int max_val = 200;
int campo[max_val][max_val]{};

void semina(const int x1, const int x2, const int y1, const int y2)//Qui ho fatto in modo che x1<x2 e y1<y2
{
    for(register int i{x1}; i<x2; ++i)
    {
        for(register int j{y1}; j<y2; ++j)
        {
            ++campo[i][j];
        }
    }
}

int totale()
{
    int tot{}, massimo{};
    for(register int i{}; i<max_val; ++i)
    {
        for(register int j{}; j<max_val; ++j)
        {
            if(massimo < campo[i][j])
            {
                tot = massimo = campo[i][j];
            }
            else if(massimo == campo[i][j])
            {
                tot += campo[i][j];
            }
        }
    }
    return tot;
}

int main()
{
    FILE* fin = fopen("input.txt", "r");
    FILE* fout = fopen("output.txt", "w");
    int N;
    assert( 1 == fscanf(fin, "%d", &N) );
    for(register int i{}; i<N; ++i)
    {
        int a,b,c,d;
        assert( 4 == fscanf(fin, "%d %d %d %d", &a, &b, &c, &d) );
        semina(a+99,c+99,d+99,b+99);
    }
    fprintf(fout, "%d", totale());
    fclose(fin);
    fclose(fout);
    return 0;
}

Dati di output
L’output è costituito da un unico numero intero non negativo: quanti semi Mario ha messo, al termine di tutte le semine, nella zona dove ve ne sono di più.

In questo momento mi viene un dubbio però, cosa bisogna fare se due zone distinte del campo possiedono lo stesso numero di semi per metro quadro?
Se per esempio la zona A(-10, 50, 21, 45) e la zona B(-90, 0, 0, -90) possiedono entrambe 4 semi per cella bisogna restituire il numero di semi totali nelle due zone o solo della zona B?

Dal punto di vista logico dovrebbe essere giusto, cerca di correggere qualche svista “sintattica” semplicemente provando il codice in locale , anche con i casi di esempio. Piccolo hint , anche se non molto influente potresti “aggiornare” la variabile “totale” all’interno della funzione semina.

In realtà non serve nemmeno fare cambiamento, basta solo prendere i valori in input , eseguire il +99, aggiornare la matrice e verificare in quale casella si trova il valore massimo .[quote=“Tredici, post:1, topic:4677”]
In questo momento mi viene un dubbio però
[/quote]

Non sono sicuro se si possa verificare, ma nel caso succeda basta dire solamente i semi contenuti in una delle 2 o più “celle”, quindi anche sotto quel punto di vista non ci sono problemi.

Grazie per il consiglio su dove aggiornare totale, non ci avevo pensato poiché con un secondo di tempo me la sono presa comoda.
Con “sintattica” intendi che ho confuso una variabile con un’altra?
Scusa sono un po’ fuso e probabilmente anche se l’errore ti sarà sembrato palese ora come ora non lo trovo.
P.S.: se c’è non dirmi dov’è che fare pratica cercando gli errori nel codice è una cosa che per quanto noiosa sia devo fare.

Non ho mai visto inizializzare la variabili con le parentesi graffe, non ho mai provato però mi ha lasciato perplesso, forse è colpa di quello?
Chiedo umilmente scusa se non è questo :sweat_smile:

1 Mi Piace

Il mio consiglio principale è prendere per esempio prendere questo codice e dati di input dei quali conosci com esattezza i dati di output, gli esempi.
La soluzione migliore è quella efficace al 100% è prendere il codice portarlo in locale e per esempio partire verificando l output finale se non si capisce perché risulti quel numero iniziare a fare il debug di ogni variabile, per esempio guardi tramite output quanto valgono in tuoi valori di x e y ogni ciclo e vedi se corrispondono, stessa cosa per il totale e se vuoi direttamente la matrice, a quel punto verifichi se i valori delle variabili corrispondono, nel momento in cui una nonna corrisponde allora guardi dove viene modificata e se viene modificata in modo corretto fino a quando l output totale è corretto. È il modo migliore per debuggare.

Onestamente nemmeno io, solo che non sono sicuro sia sbagliato e quindi ho consiglato il debug :sweat_smile:

Comunque ho corretto il codice così https://pastebin.com/yWM2Vs03 ed ora da 100/100.

Le cose che ho corretto in quanto non ero sicuro della loro correttezza sono:

  • Ho trasformato tutti i “register int i{x1}” in “int i=x1”
    -Ho cambiato queste dichiarazioni “int tot{}, massimo{};” in int tot=0, massimo=0;
    -Ho semplificato la ricerca del massimo in un banale
    • int tot=0;
      -for(int i=0; i<max_val; ++i)
      -{
      — for(int j=0; j<max_val; ++j)
      ---- if(tot <campo[i][j])
      ----- tot=campo[i][j];
  • }

E’ una novità del C++11.
L’ho trovata nel libro di Bjarne Stroustrup “C++ linguaggio libreria standard principi di programmazione”.
L’inizializzazione con parentesi graffe in (molta) sintesi funziona così:
sia T un tipo qualsiasi

T var{};/*var contiene il valore predefinito per il suo tipo es. 0 per gli int, nullptr per i puntatori, 0.0 per i double, "" per le string*/

Per i tipi classe/struct viene invocato il costruttore predefinito.

T var{ valore };

In questo caso la cosa diventa leggermente più complicata, se T è un tipo che non è inizializzabile tramite una initializer_list allora (se valore è un T oppure può essere converto in un T) var conterrà valore. Questa forma è del tutto equivalente a

T var = valore;

mentre se T può essere inizializzato con una initializer_list allora sarà invocato, a prescindere dal numero di elementi tra parentesi, il costruttore che sfrutta la initializer_list se la cosa è sensata.

vector<int> v1;
vector<int> v2{};//Come sopra
vector<int> v3{ 15, 18, 33, 36};//v3 conterrà quattro elementi rispettivamente 15,18,33 e 36
vector<int> v4(8);//v4 conterrà 8 elementi tutti a 0
vector<int> v5{8};//v5 conterrà un solo elemento: 8
vector<int> v6(15, -1);//v6 conterrà 15 elementi tutti a -1
vector<int> v7{15, -1};//v7 conterrà 2 elementi: 15 e -1
vector<int> v8{v3};//v8 sarà una copia di v3 :-> inizializzazione per copia perché è l'unica sensata
vector<int> v9{ move(v6) };//v9 "ruberà" il contenuto di v6 :-> inizializzazione per spostamento

L’inizializzazione con parentesi graffe può essere usata anche in combinazione con la keyword spostamento
auto (sempre del C++11) per chi la conosce.
Spero che questa piccola spiegazione possa essere utile a chiarire le mie intenzioni e magari anche che possa essere d’insegnamento per qualcuno.
(Chiedo perdono agli admin se l’ho messa in questo post ma aprire una nuova pagina per una spiegazione così mi sembrava eccessivo, oppure non va bene?)

Mi sono reso contro di aver letto finora 6 al posto di 2 nell’output bonus…
Avevo capito che l’output richiesto fosse quindi tutt’altra cosa, la cosa è assai imbarazzante.
Mi scuso umilmente per il disturbo arrecatovi per la mia distrazione.

Onestamente non lo sapevo , non so se il c++ 11 sia stato ancora implementato nei server di cms ma vedendo il risultato del tuo primo algoritmo non credo.

E’ stato implementato poiché varie sue novità le uso spesso (quella delle graffe in primis) e funzionano sempre, inoltre c’è anche scritto da qualche parte sul forum che il correttore lo riconosce.
Il mio algoritmo non funzionava perché restituivo il valore della variabile sbagliata (tot invece di massimo) poiché avevo frainteso la consegna del problema.
Comunque il C++11 introduce varie novità interessanti al linguaggio tra le quali le funzioni lambda, il range-for, funzioni constexpr (espressioni cotanti se vuoi ricercarle in italiano, utili per il calcolo in fase di compilazione) e altre cosette utili che nelle gare possono essere utili e comode ma rivelano appieno la loro utilità quando si tratta di scrivere programmi che non siano concisi come quelli per le gare.
Se ti piace usare il C++ e non lo usi solo per le gare ti consiglio di vedere cosa aggiunge lo standard.

:joy:

2 Mi Piace