POJ 2958

解き方に気づけば簡単。ちなみに最初に斜めのラインで部分和を計算しておけば、とか思ったけどナイーブな方法と変わらないぐらい遅かった。

#include <iostream>
#include <algorithm>
#include <numeric>

using namespace std;

static const int N = 100;

static int
optimal(int *d, int n, int total)
{
  int upside = 0;
  int downside = total;
  int m = 0;
  int cur = 0;

  for (int i = 0; i < n - 1; i++)
    {
      upside += d[i];
      downside -= d[i];
      cur += upside - (total - upside);
      m = cur < m ? cur : m;
    }

  return m;
}

int
main()
{
  int t;
  cin >> t;
  while (t--)
    {
      int rows, columns;
      int base_cost = 0;        // cost from (0, 0)
      int total = 0;            // sum of count for all blocks
      int sum_v[N];             // sum of count for each vertical area
      int sum_h[N];             // sum of count for each horizontal area

      cin >> columns >> rows;
      fill(sum_h, sum_h + rows, 0);
      fill(sum_v, sum_v + columns, 0);

      for (int i = 0; i < rows; i++)
        {
          for (int j = 0; j < columns; j++)
            {
              int x;
              cin >> x;
              sum_h[i] += x;
              sum_v[j] += x;
              base_cost += (i + j) * x;
            }

          total += sum_h[i];
        }

      int result = base_cost
        + optimal(sum_h, rows, total)
        + optimal(sum_v, columns, total);
      cout << result << " blocks" << endl;
    }

  return 0;
}

で、適当に縮める。

#import<algo.h>

int a, t, b, x, y, v[100], h[100], i, j;

int
o(int *d)
{
  int i, u, c;
  for (u=c=a=i=0;i<100;d[i++]=0)
    u+=d[i]*2,c+=u-t,a<?=c;
}

int
main()
{
  for(cin>>x;cin>>x>>y;cout<<b+o(h)+o(v)<<" blocks\n",t=b=0)
      for (i = 0; i < y; i++)
          for (j = 0; j < x; j++)
            cin>>a,h[i]+=a,v[j]+=a,b+=(i+j)*a,t+=a;
}

空白を削って 265B。まだまだ削れそうだけど、とりあえずこの辺で。