/* FILE: monoKnap.cpp last change: 3-Jul-2014 author: Romeo Rizzi * a DP solver for problem "monoKnap" */ //#define NDEBUG // NDEBUG definita nella versione che consegno #include #ifndef NDEBUG # include // uso di cin e cout non consentito in versione finale #endif #include using namespace std; const int LIST = 100000; const int MAX_B = 1000; int B; const int MAX_N = 100; int n; int p[MAX_N]; // i pesi e gli oggetti sono indicizzati partendo da zero int opt[MAX_N+1][MAX_B+1]; /* where opt[i][b] will store the maximum sum non exceeding b, for a non-decreasing subsequence of p[0],p[1],...,p[n-1] which takes object i as its very first object. We have added an object p_n = 0 as sentinel to simplify the base case. */ int glob_opt = 0; int printed = 0; int taken[MAX_N]; #ifndef NDEBUG void displayVect(int vect[], int n) { for(int i = 0; i < n; i++) cout << vect[i] << " "; cout << endl; } #endif int myMax( int a, int b ) { return (a>b)? a : b; } ofstream fout("output.txt"); void listLexOptSols(int from, int LB, int gathered) { // il vettore taken[0..from-1] specifica quali elementi a sinistra di sono gia' presi raccogliendo gia' una somma parziale // dobbiamo scegliere chi eventualmente prendere da in poi, col primo non inferiore a , per formare sottosequenza non-decrescente a valore complessivo precisamente uguale a glob_opt. assert( from <= n ); if(printed >= LIST) return; if( from == n ) { if( gathered == glob_opt ) { for(int i = 0; i < n; i++) if( taken[i] == 1 ) fout << p[i] << " "; fout << endl; printed++; } return; } if( (p[from] >= LB) && ( p[from] + gathered <= B) ) if( gathered + opt[from][B-gathered] >= glob_opt ) { taken[from] = 1; listLexOptSols(from+1, p[from], gathered + p[from]); } taken[from] = 0; listLexOptSols(from+1, LB, gathered); } int main() { ifstream fin("input.txt"); assert( fin ); fin >> n >> B; assert( n <= MAX_N ); assert( B <= MAX_B ); for(int i = 0; i < n; i++) fin >> p[i]; fin.close(); //displayVect(p, n); for(int i = n-1; i >= 0; i--) { for(int b = 0; b <= B; b++) { opt[i][b] = 0; if( p[i] <= b ) { opt[i][b] = p[i]; for(int j = i+1; j < n; j++) if( p[j] >= p[i] ) opt[i][b] = myMax(opt[i][b], p[i]+opt[j][ b-p[i] ]); } } glob_opt = myMax(glob_opt, opt[i][ B ]); } fout << glob_opt << endl; listLexOptSols(0, 0, 0); fout.close(); return 0; }