A General Idea

The solution is based on this: After setting up k points, only the minimal rectangle covering all the existing points is of importance to us. Start with K = 0, 1, 2 .. etc. and progress.

Why is this the case?

1) For the points inside the rectangle which have not yet been set up, the cost for setting up those is fixed: the sum of the maximum distance between each of them to the edge of the rectangle.

2) For the points outside the rectangle, the maximum distance will only be dependent on the points in this rectangle, because the oil wells inside that rectangle cannot be a a greater distance.

So let us start with this easy Dynamic Programming function, by using the above mentioned rule inductively:

Let F(lx, ly, rx, ry) be the cost of setting up all the oil wells inside rectangle with top-left corner at coordinates (lx, ly) and bottom-right corner at coordinates (rx, ry).

F(lx, ly, rx, ry) = min(F(lx’, ly’, rx’, ry’) + cost_of_points_not_set_up)

n <= 50
The upper bound on the number of points is O(n ^ 2).

There are n ^ 4 states, and we need to enumurate (lx’, ly’, rx’, ry’) which will be done O(n ^ 4) times, and we need to calculate the cost which can be done in O(n ^ 2) time, so the total complexity is O(n ^ 10).

How do we optimize this?>

As we can see, if there are at least one point strictly between (lx, ly, rx, ry) and (lx’, ly’, rx’, ry’), the cost will not be optimal. So, we add the inner points first before expanding the rectangle.

Here is the rule we will enforce: While adding a new point, the new rectangle can not contain any point which is strictly inside it.

So the choice of (lx’, ly’, rx’, ry’) will be restricted. And we can calculate the cost of the new points in O(n). So the complexity can be optimized to O(n ^ 4) * O(n) = O(n ^ 5).

Solution:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const int inf = 1000000000;
const int N = 52;
int dp[N][N][N][N], a[N][N];

int ab(int x) {
    return (x > 0)?x:(-x);
}

int dis(int x1,int y1,int x2,int y2) {
    return max(ab(x1 - x2), ab(y1 - y2));
}

int cal(int x,int y,int x1,int y1,int x2, int y2) {
    return max(dis(x,y,x1,y1), dis(x,y,x2,y2));
}


int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */  
    int m, n;
    scanf("%d%d",&m,&n);
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            scanf("%d",&a[i][j]);
        }
    }
    for (int i = m - 1; i >= 0; --i) {
        for (int j = n - 1; j >= 0; --j) {
            for (int k = i; k < m; ++k) {
                for (int h = (k == i)?(j + 1):j; h < n; ++h) {
                    dp[i][j][k][h] = inf;
                   
                    if (i < k) {
                        int may = dp[i + 1][j][k][h]; 
                        for (int y = j; y <= h; ++y) {
                            if (a[i][y]) {
                                may += cal(i, y, i + 1, j, k, h);
                            }
                        
                        }
                        dp[i][j][k][h] = min(dp[i][j][k][h], may);
                        may = dp[i][j][k - 1][h];
                        for (int y = j; y <= h; ++y) {
                            if (a[k][y]) {
                                may += cal(k, y, i ,j, k - 1, h);
                            
                            }
                        }
                        dp[i][j][k][h] = min(dp[i][j][k][h], may);
                    }
                    if (j < h) {
                        int may = dp[i][j + 1][k][h];
                        for (int x = i; x <= k; ++x) {
                            if (a[x][j]) {
                                may += cal(x, j, i, j + 1, k, h);
                            }
                        }
                        dp[i][j][k][h] = min(dp[i][j][k][h], may);
                        may = dp[i][j][k][h - 1];
                        for (int x = i; x <= k; ++x) {
                            if (a[x][h]) {
                                may += cal(x, h, i, j, k, h - 1);
                            }
                        }
                        dp[i][j][k][h] = min(dp[i][j][k][h], may);
                        
                    }
                    
                }
            }
        }
    }
    printf("%d\n",dp[0][0][m - 1][n - 1]);
    return 0;
}