/* FILE: tripletteRic.cpp last change: 7-Nov-2012 author: Romeo Rizzi * a recursive (exponential) 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 UNFEASIBLE = INT_MAX; 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). 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 /* OUR PLAN/VIEW ON THE PROBLEM: Obs 0: permuting the numbers in input has no effect on the problem, the optimal solution does not change. It is hence a good idea to first sort the numbers in input. We assumes the input integers have been sorted so that numero[0], ..., numero[n-1] is a non-decreasing sequence. Consider to be given an optimal solution. Represent it by means of a graph which has the numbers as nodes and an edge connecting the two closest numbers in every triplet. This is a matching of size t=n/3. One of minimum cost, where the cost of an edge is the difference between its endnodes. Furthermore, if the nodes are placed on the line in their order after sorting, then it can be observed that each edge in the matching connects two consecutive nodes. This motivates to introduce the following family of problems, closed over induction: */ int opt(int i, int k) {// returns the minimum cost of a matching of size k within the weighted graph induced by the numbers in numero[0..i] if( k == 0 ) return 0; if( 2*k > i+1 ) return UNFEASIBLE; int risp = opt(i-1, k); int tmp = opt(i-2, k-1); if( tmp != UNFEASIBLE ) risp = min( risp, tmp + numero[i] - numero[i-1] ); #ifndef NDEBUG cout << "opt(" << i << ", " << k << ") = " << risp << endl; #endif return risp; } int main() { ifstream fin("input.txt"); assert( fin ); fin >> n; for(int i = 0; i < n; i++) fin >> numero[i]; fin.close(); //displayVect(numero, n); sort(numero, n); //displayVect(numero, n); int t = n/3; ofstream fout("output.txt"); fout << opt(n-1, t) << endl; fout.close(); return 0; }