/* FILE: tripletteCubic.cpp last change: 7-Nov-2012 author: Romeo Rizzi * a polytime (but cubic) solver for problem "triplette" */ #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, vect[MAX_N]; int minCost[MAX_N +1][MAX_N +1]; /* assumes the input integers have been sorted so that vect[0], ..., vect[n-1] is non-increasing. Once this is done, it can be proven that there always exists an optimal solution where the two leftmost elements of each triplet are consecutive. We call these two elements the "head" of the triplet, the "third" element is called "tail". We search for an optimum solution among those which have this structure (no head is split) and call them "canonical solutions". minCost[from][num_t] will store the minimum cost of a partition of the interval vect[from, from + 3*num_t -1] into precisely num_t triplets. */ void swap(int &a, int &b) { int tmp = a; a = b; b = tmp; } void sort(int vect[], int n) { if( n > 1 ) { for(int i = 0; i < n-1; i++) if( vect[n-1] > vect[i] ) swap(vect[n-1], vect[i]); sort(vect, n-1); } } #ifndef NDEBUG void displayVect(int vect[], int n) { for(int i = 0; i < n; i++) cout << vect[i] << " "; cout << endl; } #endif int main() { ifstream fin("input.txt"); assert(fin); fin >> n; for(int i = 0; i < n; i++) fin >> vect[i]; fin.close(); //displayVect(vect, n); sort(vect, n); //displayVect(vect, n); for(int num_t = 0; num_t <= n; num_t++) for(int from = 0; from + 3*num_t <= n; from++) if( num_t == 0 ) minCost[from][num_t] = 0; else { // the first two elements of the interval necessarily form an head // as first viable option, the very last element of the interval is the tail for this head: minCost[from][num_t] = minCost[from +2][num_t-1] + ( vect[from] -vect[from +1] ) * ( vect[from] -vect[from +1] ); // otherwise the interval can be split into two subintervals somewhere: for(int num_other_t = 1; num_other_t < num_t; num_other_t++) minCost[from][num_t] = min( minCost[from][num_t], minCost[from][num_other_t] + minCost[from +3*num_other_t][num_t -num_other_t] ); #ifndef NDEBUG cout << "minCost[" << from << "][" << num_t << "] = " << minCost[from][num_t] << endl; #endif } ofstream fout("output.txt"); assert(fout); fout << minCost[0][n/3] << endl; fout.close(); return 0; }