0w1

UVA 11997 - K Smallest Sums ( Priority Queue, Merge )

UVa Online Judge
First I thought I could simply make a structure to record where each index of the arrays are, and expand them in priority queue, however, did not work out because for example when ( 0, 1 ) and ( 1, 0 ) are both visited, ( 1, 1 ) will be visited twice. Anyways, we will come up to that the number of arrays can be reduced, as a bunch of subproblems, merging each pair of arrays until there is only one left. This problem is a good example for the approach of simplifying the original problem to find the relation.

typedef pair< int, int > pii;
typedef vector< int > vi;
typedef vector< vi > vvi;

vi merge( const vi &a, const vi &b ){
    vi res;
    priority_queue< pii, vector< pii >, greater< pii > > pq;
    for( int i = 0; i < a.size(); ++i )
        pq.push( pii( a[ i ] + b[ 0 ], 0 ) );
    while( res.size() < a.size() ){
        int sum = pq.top().first;
        int bid = pq.top().second;
        pq.pop();
        res.push_back( sum );
        if( bid + 1 < b.size() )
            pq.push( pii( sum - b[ bid ] + b[ bid + 1 ], bid + 1 ) );
    }
    return res;
}

void solve( int N ){
    vvi A( N, vi( N ) );
    for( int i = 0; i < N; ++i )
        for( int j = 0; j < N; ++j )
            cin >> A[ i ][ j ];

    for( int i = 0; i < N; ++i )
        sort( A[ i ].begin(), A[ i ].end() );

    vi cur = A[ 0 ];
    for( int i = 1; i < N; ++i )
        cur = merge( cur, A[ i ] );

    for( int i = 0; i < N; ++i )
        cout << cur[ i ] << ( i + 1 == N ? '\n' : ' ' );
}