0w1

ABC 8 D - 金塊ゲーム ( DP )

D: 金塊ゲーム - AtCoder Beginner Contest 008 | AtCoder
Let dp[ i ][ j ][ k ][ l ]: maximum score for rectangle upper left ( i, j ) lower right ( k, l )
f:id:h0rnet:20160308212908p:plain
( taken from AtCoder Beginner Contest 008 解説 )
we can split the problem into four sub problems for the four corners.
dp[ i ][ j ][ k ][ l ] = k - i + l - j + 1 + max{ dp[ i ][ j ][ mx - 1 ][ my - 1 ] + dp[ i ][ my + 1 ][ mx - 1 ][ l ] + dp[ mx + 1 ][ j ][ k ][ my - 1 ] + dp[ mx + 1 ][ my + 1 ][ k ][ l ] } Ɐ i ≤ mx ≤ k && j ≤ my ≤ l
even if it goes outside of bound i.e. when i = mx and tries to sum up [ i ][ i - 1 ] it will be alright since it's still 0.

#include <bits/stdc++.h>
using namespace std;
const int MAXW = 1e6 + 6;
const int MAXH = 1e6 + 6;
const int MAXN = 30 + 3;
typedef long long ll;
#define rep( i, a ) for(int i = 0; i < (int)( a ); ++i)

int w, h, n;
int x[ MAXN ], y[ MAXN ];

map< tuple<int, int, int, int>, ll > mtl;

ll dp(int x0, int y0, int x1, int y1){
    auto idx = make_tuple( x0, y0, x1, y1 );
    if( mtl.count( idx ) ) return mtl[ idx ];
    rep( i, n ) if( x0 <= x[ i ] && x[ i ] <= x1 && y0 <= y[ i ] && y[ i ] <= y1 ){
        mtl[ idx ] = max<ll>( mtl[ idx ], x1 - x0 + y1 - y0 + 1
                            + dp( x[ i ] + 1, y[ i ] + 1, x1, y1 )
                            + dp( x[ i ] + 1, y0, x1, y[ i ] - 1 )
                            + dp( x0, y[ i ] + 1, x[ i ] - 1, y1 )
                            + dp( x0, y0, x[ i ] - 1, y[ i ] - 1 ) );
    }
    return mtl[ idx ];
}

int main(){
    scanf("%d%d%d", &w, &h, &n);
    rep( i, n ) scanf("%d%d", &y[ i ], &x[ i ]);
    printf("%lld\n", dp( 1, 1, h, w));
    return 0;
}