#include <iostream>
#include <vector>
#include <utility>
#include <iterator>
#include <string>
#include <sstream>
//#include "sequence_lister.h"
using namespace std;
#define INF 1000000000
class MaxMinGap {
vector< int > x;
int M;
const int N; // Just for convenience -- it's just x.size()
vector< vector< int > > fMemo;
vector< vector< int > > pred; // Stores d values, from which the right i and j can be computed
int bestM;
// The following version finds solutions having *exactly* the given number of deletions,
// which is what we need to get the right answer.
int f( int i, int j) {
if ( i == N - 1 ) {
if ( j > 0 ) {
return 0 ; // The deletions won't all fit
} else {
return INF;
}
}
if ( fMemo[ i] [ j] == - 1 ) {
int best = - 1 ;
int bestD = - 1 ;
for ( int d = 0 ; d <= min( j, N - i - 2 ) ; ++ d) {
int guess = min( x[ i + d + 1 ] - x[ i] , f( i + d + 1 , j - d) ) ;
if ( guess > best) {
best = guess;
bestD = d;
}
}
fMemo[ i] [ j] = best;
pred[ i] [ j] = bestD;
}
return fMemo[ i] [ j] ;
}
public :
MaxMinGap( vector< int > x, int M) : x( x) , M( M) , N( x.size ( ) ) , fMemo( x.size ( ) + 1 , vector< int > ( M + 1 , - 1 ) ) , pred( x.size ( ) + 1 , vector< int > ( M + 1 , - 1 ) ) , bestM( INF) {
solve( ) ; // Might as well do it right away
}
// Must be called before getSolution() or getBestMinGapSize()
void solve( ) {
int best;
for ( int i = M; i >= 0 ; -- i) {
int guess = f( 0 , i) ;
if ( i < M && guess < best) {
break ;
}
best = guess;
bestM = i;
}
}
// The following version doesn't find the solution having the minimum number of deletions!
//int f(int i, int j) {
// if (i == N - 1) {
// return INF;
// }
//
// if (fMemo[i][j] == -1) {
// int best = -1;
// int bestD = -1;
// for (int d = 0; d <= min(j, N - i - 2); ++d) {
// int guess = min(x[i + d + 1] - x[i], f(i + d + 1, j - d));
// if (guess > best) {
// best = guess;
// bestD = d;
// }
// }
//
// fMemo[i][j] = best;
// pred[i][j] = bestD;
// }
//
// return fMemo[i][j];
//}
// Wrongheaded! Lacks optimal substructure on close inspection.
//// The second element is the number of deletions that weren't needed, so
//// that comparisons can be done with a simple ">".
//pair<int, int> f(int i, int j) {
// if (i == N - 1) {
// return make_pair(INF, j);
// }
//
// if (fMemo[i][j].first == -1) {
// pair<int, int> best = make_pair(-1, -1);
// int bestD = -1;
// for (int d = 0; d <= min(j, N - i - 2); ++d) {
// pair<int, int> subproblem = f(i + d + 1, j - d);
// pair<int, int> guess;
// guess.first = min(x[i + d + 1] - x[i], subproblem.first);
// guess.second = subproblem.second;
// if (guess > best) {
// best = guess;
// bestD = d;
// }
// }
//
// fMemo[i][j] = best;
// pred[i][j] = bestD;
// }
//
// return fMemo[i][j];
//}
// solve() must be run first.
int getBestMinGapSize( ) {
return f( 0 , bestM) ;
}
// solve() must be run first.
int getFewestDeletions( ) {
return bestM;
}
// solve() must be run first.
vector< int > getSolution( ) {
vector< int > numbers;
int i = 0 , j = bestM;
while ( pred[ i] [ j] ! = - 1 ) {
numbers.push_back ( x[ i] ) ;
int d = pred[ i] [ j] ;
i + = d + 1 ;
j - = d;
}
numbers.push_back ( x[ N - 1 ] ) ;
return numbers;
}
} ;
// Function template for joining sequences into strings
template < typename C>
string list_sequence( C c, string delim) {
ostringstream oss;
for ( typename C:: const_iterator i( c.begin ( ) ) ; i ! = c.end ( ) ; ++ i) {
if ( i ! = c.begin ( ) ) {
oss << delim;
}
oss << * i;
}
return oss.str ( ) ;
}
int main( int argc, char ** argv) {
cout << "Enter M (maximum number of numbers to delete): " ;
int M;
cin >> M;
cout << "\n Enter numbers (Ctrl-Z to end): " ;
MaxMinGap mmg( vector< int > ( istream_iterator< int > ( cin ) , istream_iterator< int > ( ) ) , M) ;
cout << "\n Best solution has a minimum gap size of " << mmg.getBestMinGapSize ( ) << ", with " << mmg.getFewestDeletions ( ) << " deletions needed.\n " ;
cout << "Example optimal solution: " << list_sequence( mmg.getSolution ( ) , " " ) << ".\n " ;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8c3N0cmVhbT4KLy8jaW5jbHVkZSAic2VxdWVuY2VfbGlzdGVyLmgiCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKI2RlZmluZSBJTkYgMTAwMDAwMDAwMAoKY2xhc3MgTWF4TWluR2FwIHsKICAgIHZlY3RvcjxpbnQ+IHg7CglpbnQgTTsKCWNvbnN0IGludCBOOwkJLy8gSnVzdCBmb3IgY29udmVuaWVuY2UgLS0gaXQncyBqdXN0IHguc2l6ZSgpCgl2ZWN0b3I8dmVjdG9yPGludD4gPiBmTWVtbzsKCXZlY3Rvcjx2ZWN0b3I8aW50PiA+IHByZWQ7CQkvLyBTdG9yZXMgZCB2YWx1ZXMsIGZyb20gd2hpY2ggdGhlIHJpZ2h0IGkgYW5kIGogY2FuIGJlIGNvbXB1dGVkCglpbnQgYmVzdE07CgkKCS8vIFRoZSBmb2xsb3dpbmcgdmVyc2lvbiBmaW5kcyBzb2x1dGlvbnMgaGF2aW5nICpleGFjdGx5KiB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlbGV0aW9ucywKCS8vIHdoaWNoIGlzIHdoYXQgd2UgbmVlZCB0byBnZXQgdGhlIHJpZ2h0IGFuc3dlci4KCWludCBmKGludCBpLCBpbnQgaikgewoJCWlmIChpID09IE4gLSAxKSB7CgkJCWlmIChqID4gMCkgewoJCQkJcmV0dXJuIDA7CQkvLyBUaGUgZGVsZXRpb25zIHdvbid0IGFsbCBmaXQKCQkJfSBlbHNlIHsKCQkJCXJldHVybiBJTkY7CgkJCX0KCQl9CgkJCgkJaWYgKGZNZW1vW2ldW2pdID09IC0xKSB7CgkJCWludCBiZXN0ID0gLTE7CgkJCWludCBiZXN0RCA9IC0xOwoJCQlmb3IgKGludCBkID0gMDsgZCA8PSBtaW4oaiwgTiAtIGkgLSAyKTsgKytkKSB7CgkJCQlpbnQgZ3Vlc3MgPSBtaW4oeFtpICsgZCArIDFdIC0geFtpXSwgZihpICsgZCArIDEsIGogLSBkKSk7CgkJCQlpZiAoZ3Vlc3MgPiBiZXN0KSB7CgkJCQkJYmVzdCA9IGd1ZXNzOwoJCQkJCWJlc3REID0gZDsKCQkJCX0KCQkJfQoJCQkKCQkJZk1lbW9baV1bal0gPSBiZXN0OwoJCQlwcmVkW2ldW2pdID0gYmVzdEQ7CgkJfQoJCQoJCXJldHVybiBmTWVtb1tpXVtqXTsKCX0KCQpwdWJsaWM6CglNYXhNaW5HYXAodmVjdG9yPGludD4geCwgaW50IE0pIDogeCh4KSwgTShNKSwgTih4LnNpemUoKSksIGZNZW1vKHguc2l6ZSgpICsgMSwgdmVjdG9yPGludD4oTSArIDEsIC0xKSksIHByZWQoeC5zaXplKCkgKyAxLCB2ZWN0b3I8aW50PihNICsgMSwgLTEpKSwgYmVzdE0oSU5GKSB7CgkJc29sdmUoKTsJCS8vIE1pZ2h0IGFzIHdlbGwgZG8gaXQgcmlnaHQgYXdheQoJfQoJCgkvLyBNdXN0IGJlIGNhbGxlZCBiZWZvcmUgZ2V0U29sdXRpb24oKSBvciBnZXRCZXN0TWluR2FwU2l6ZSgpCgl2b2lkIHNvbHZlKCkgewoJCWludCBiZXN0OwoJCWZvciAoaW50IGkgPSBNOyBpID49IDA7IC0taSkgewoJCQlpbnQgZ3Vlc3MgPSBmKDAsIGkpOwoJCQlpZiAoaSA8IE0gJiYgZ3Vlc3MgPCBiZXN0KSB7CgkJCQlicmVhazsKCQkJfQoJCQkKCQkJYmVzdCA9IGd1ZXNzOwoJCQliZXN0TSA9IGk7CgkJfQoJfQoJCgkvLyBUaGUgZm9sbG93aW5nIHZlcnNpb24gZG9lc24ndCBmaW5kIHRoZSBzb2x1dGlvbiBoYXZpbmcgdGhlIG1pbmltdW0gbnVtYmVyIG9mIGRlbGV0aW9ucyEKCS8vaW50IGYoaW50IGksIGludCBqKSB7CgkvLwlpZiAoaSA9PSBOIC0gMSkgewoJLy8JCXJldHVybiBJTkY7CgkvLwl9CgkvLwkKCS8vCWlmIChmTWVtb1tpXVtqXSA9PSAtMSkgewoJLy8JCWludCBiZXN0ID0gLTE7CgkvLwkJaW50IGJlc3REID0gLTE7CgkvLwkJZm9yIChpbnQgZCA9IDA7IGQgPD0gbWluKGosIE4gLSBpIC0gMik7ICsrZCkgewoJLy8JCQlpbnQgZ3Vlc3MgPSBtaW4oeFtpICsgZCArIDFdIC0geFtpXSwgZihpICsgZCArIDEsIGogLSBkKSk7CgkvLwkJCWlmIChndWVzcyA+IGJlc3QpIHsKCS8vCQkJCWJlc3QgPSBndWVzczsKCS8vCQkJCWJlc3REID0gZDsKCS8vCQkJfQoJLy8JCX0KCS8vCQkKCS8vCQlmTWVtb1tpXVtqXSA9IGJlc3Q7CgkvLwkJcHJlZFtpXVtqXSA9IGJlc3REOwoJLy8JfQoJLy8JCgkvLwlyZXR1cm4gZk1lbW9baV1bal07CgkvL30KCQoJLy8gV3JvbmdoZWFkZWQhICBMYWNrcyBvcHRpbWFsIHN1YnN0cnVjdHVyZSBvbiBjbG9zZSBpbnNwZWN0aW9uLgoJLy8vLyBUaGUgc2Vjb25kIGVsZW1lbnQgaXMgdGhlIG51bWJlciBvZiBkZWxldGlvbnMgdGhhdCB3ZXJlbid0IG5lZWRlZCwgc28KCS8vLy8gdGhhdCBjb21wYXJpc29ucyBjYW4gYmUgZG9uZSB3aXRoIGEgc2ltcGxlICI+Ii4KCS8vcGFpcjxpbnQsIGludD4gZihpbnQgaSwgaW50IGopIHsKCS8vCWlmIChpID09IE4gLSAxKSB7CgkvLwkJcmV0dXJuIG1ha2VfcGFpcihJTkYsIGopOwoJLy8JfQoJLy8JCgkvLwlpZiAoZk1lbW9baV1bal0uZmlyc3QgPT0gLTEpIHsKCS8vCQlwYWlyPGludCwgaW50PiBiZXN0ID0gbWFrZV9wYWlyKC0xLCAtMSk7CgkvLwkJaW50IGJlc3REID0gLTE7CgkvLwkJZm9yIChpbnQgZCA9IDA7IGQgPD0gbWluKGosIE4gLSBpIC0gMik7ICsrZCkgewoJLy8JCQlwYWlyPGludCwgaW50PiBzdWJwcm9ibGVtID0gZihpICsgZCArIDEsIGogLSBkKTsKCS8vCQkJcGFpcjxpbnQsIGludD4gZ3Vlc3M7CgkvLwkJCWd1ZXNzLmZpcnN0ID0gbWluKHhbaSArIGQgKyAxXSAtIHhbaV0sIHN1YnByb2JsZW0uZmlyc3QpOwoJLy8JCQlndWVzcy5zZWNvbmQgPSBzdWJwcm9ibGVtLnNlY29uZDsKCS8vCQkJaWYgKGd1ZXNzID4gYmVzdCkgewoJLy8JCQkJYmVzdCA9IGd1ZXNzOwoJLy8JCQkJYmVzdEQgPSBkOwoJLy8JCQl9CgkvLwkJfQoJLy8JCQoJLy8JCWZNZW1vW2ldW2pdID0gYmVzdDsKCS8vCQlwcmVkW2ldW2pdID0gYmVzdEQ7CgkvLwl9CgkvLwkKCS8vCXJldHVybiBmTWVtb1tpXVtqXTsKCS8vfQoJCgkvLyBzb2x2ZSgpIG11c3QgYmUgcnVuIGZpcnN0LgoJaW50IGdldEJlc3RNaW5HYXBTaXplKCkgewoJCXJldHVybiBmKDAsIGJlc3RNKTsKCX0KCQoJLy8gc29sdmUoKSBtdXN0IGJlIHJ1biBmaXJzdC4KCWludCBnZXRGZXdlc3REZWxldGlvbnMoKSB7CgkJcmV0dXJuIGJlc3RNOwoJfQoJCgkvLyBzb2x2ZSgpIG11c3QgYmUgcnVuIGZpcnN0LgoJdmVjdG9yPGludD4gZ2V0U29sdXRpb24oKSB7CgkJdmVjdG9yPGludD4gbnVtYmVyczsKCQkKCQlpbnQgaSA9IDAsIGogPSBiZXN0TTsKCQl3aGlsZSAocHJlZFtpXVtqXSAhPSAtMSkgewoJCQludW1iZXJzLnB1c2hfYmFjayh4W2ldKTsKCQkJaW50IGQgPSBwcmVkW2ldW2pdOwoJCQlpICs9IGQgKyAxOwoJCQlqIC09IGQ7CgkJfQoJCQoJCW51bWJlcnMucHVzaF9iYWNrKHhbTiAtIDFdKTsKCQlyZXR1cm4gbnVtYmVyczsKCX0KfTsKCi8vIEZ1bmN0aW9uIHRlbXBsYXRlIGZvciBqb2luaW5nIHNlcXVlbmNlcyBpbnRvIHN0cmluZ3MKdGVtcGxhdGUgPHR5cGVuYW1lIEM+CnN0cmluZyBsaXN0X3NlcXVlbmNlKEMgYywgc3RyaW5nIGRlbGltKSB7Cglvc3RyaW5nc3RyZWFtIG9zczsKCWZvciAodHlwZW5hbWUgQzo6Y29uc3RfaXRlcmF0b3IgaShjLmJlZ2luKCkpOyBpICE9IGMuZW5kKCk7ICsraSkgewoJCWlmIChpICE9IGMuYmVnaW4oKSkgewoJCQlvc3MgPDwgZGVsaW07CgkJfQoJCQoJCW9zcyA8PCAqaTsKCX0KCQoJcmV0dXJuIG9zcy5zdHIoKTsKfQoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIgKiphcmd2KSB7Cgljb3V0IDw8ICJFbnRlciBNIChtYXhpbXVtIG51bWJlciBvZiBudW1iZXJzIHRvIGRlbGV0ZSk6ICI7CglpbnQgTTsKCWNpbiA+PiBNOwoJY291dCA8PCAiXG5FbnRlciBudW1iZXJzIChDdHJsLVogdG8gZW5kKTogIjsKCU1heE1pbkdhcCBtbWcodmVjdG9yPGludD4oaXN0cmVhbV9pdGVyYXRvcjxpbnQ+KGNpbiksIGlzdHJlYW1faXRlcmF0b3I8aW50PigpKSwgTSk7Cgljb3V0IDw8ICJcbkJlc3Qgc29sdXRpb24gaGFzIGEgbWluaW11bSBnYXAgc2l6ZSBvZiAiIDw8IG1tZy5nZXRCZXN0TWluR2FwU2l6ZSgpIDw8ICIsIHdpdGggIiA8PCBtbWcuZ2V0RmV3ZXN0RGVsZXRpb25zKCkgPDwgIiBkZWxldGlvbnMgbmVlZGVkLlxuIjsKCWNvdXQgPDwgIkV4YW1wbGUgb3B0aW1hbCBzb2x1dGlvbjogIiA8PCBsaXN0X3NlcXVlbmNlKG1tZy5nZXRTb2x1dGlvbigpLCAiICIpIDw8ICIuXG4iOwoJCglyZXR1cm4gMDsKfQo=