/* FILE: tripletteBig.cpp last change: 12-Sept-2012 author: Romeo Rizzi * an optimal (quadratic) solver for problem "tripletteBig" */ #define NDEBUG // NDEBUG definita nella versione che consegno #include #ifndef NDEBUG # include // uso di cin e cout non consentito in versione finale #endif #include #include using namespace std; const int MAX_N = 10000; // massima cardinalita' dell'insieme di numeri fornito in input int n; int numero[MAX_N]; // gli n numeri in input. (Poi ordinati subito a valle della lettura). int opt[MAX_N][MAX_N]; /* assumes the input integers have been sorted so that numero[0], ..., numero[n-1] is non-decreasing. Once this is done, it can be proven that there always exists an optimal solution where the two rightmost elements of each triplet are consecutive. We call these two elements the "head" of the triplet, and search for an optimum solution among those which have this structure (no head is split). opt[n_tripleIntere][n_codeSole] will store the minimum cost of a partial solution which in a prefix of the array numero[] places whole triplets (paying for their twin head elements) plus further elements (bound to belong to different triplets!). (All these 3*n_tripleIntere + n_codeSole elements should cover a consecutive prefix with no holes). */ int main() { ifstream fin("input.txt"); assert( fin ); fin >> n; for(int i = 0; i < n; i++) fin >> numero[i]; fin.close(); sort(numero, numero + n); int t = n/3; // conviene lavorare con t = n/3 for(int n_tripleIntere = 0; n_tripleIntere <= t; n_tripleIntere++) for(int n_codeSole = 0; n_codeSole + n_tripleIntere <= t; n_codeSole++) { int n_numeri = 3*n_tripleIntere + n_codeSole; if( n_tripleIntere == 0 ) opt[n_tripleIntere][n_codeSole] = 0; else { // un eventualita' sempre possibile e' che il numero piu' a destra nel prefisso chiuda una tripla: opt[n_tripleIntere][n_codeSole] = opt[ n_tripleIntere - 1 ][ n_codeSole + 1 ] + (numero[n_numeri-1] - numero[n_numeri-2]) * (numero[n_numeri-1] - numero[n_numeri-2]); if( n_codeSole > 0 ) // l'altra possibilita' e' che sia solo opt[n_tripleIntere][n_codeSole] = min( opt[n_tripleIntere][n_codeSole], opt[ n_tripleIntere ][ n_codeSole - 1 ] ); #ifndef NDEBUG cout << "opt[" << n_tripleIntere << "][" << n_codeSole << "] = " << opt[n_tripleIntere][n_codeSole] << endl; #endif } } ofstream fout("output.txt"); fout << opt[t][0] << endl; fout.close(); return 0; }