description: CQXYM found a rectangle A of size n × m. There are n rows and m columns of blocks. Each block of the rectangle is an obsidian block or empty. CQXYM can change an obsidian block to an empty block or an empty block to an obsidian block in one operation.
  
  A rectangle M size of a × b is called a portal if and only if it satisfies the following conditions:
  
    * a ≥ 5,b ≥ 4. 
    * For all 1 < x < a, blocks M_{x,1} and M_{x,b} are obsidian blocks. 
    * For all 1 < x < b, blocks M_{1,x} and M_{a,x} are obsidian blocks. 
    * For all 1<x<a,1<y<b, block M_{x,y} is an empty block. 
    * M_{1, 1}, M_{1, b}, M_{a, 1}, M_{a, b} can be any type. 
  
  Note that the there must be a rows and b columns, not b rows and a columns.
  
  Note that corners can be any type
  
  CQXYM wants to know the minimum number of operations he needs to make at least one sub-rectangle a portal.
  
  Input
  
  The first line contains an integer t (t ≥ 1), which is the number of test cases.
  
  For each test case, the first line contains two integers n and m (5 ≤ n ≤ 400, 4 ≤ m ≤ 400). 
  
  Then n lines follow, each line contains m characters 0 or 1. If the j-th character of i-th line is 0, block A_{i,j} is an empty block. Otherwise, block A_{i,j} is an obsidian block.
  
  It is guaranteed that the sum of n over all test cases does not exceed 400.
  
  It is guaranteed that the sum of m over all test cases does not exceed 400.
  
  Output
  
  Output t answers, and each answer in a line.
  
  Examples
  
  Input
  
  
  1
  5 4
  1000
  0000
  0110
  0000
  0001
  
  
  Output
  
  
  12
  
  
  Input
  
  
  1
  9 9
  001010001
  101110100
  000010011
  100000001
  101010101
  110001111
  000001111
  111100000
  000110000
  
  
  Output
  
  
  5
  
  Note
  
  In the first test case, the final portal is like this:
      
      
        
      1110  
      1001  
      1001  
      1001  
      0111  
      
solution: #include <bits/stdc++.h>
  using namespace std;
  const int N = 405;
  template <typename T>
  void read(T &x) {
    bool neg = false;
    unsigned char c = getchar();
    for (; (c ^ 48) > 9; c = getchar())
      if (c == '-') neg = true;
    for (x = 0; (c ^ 48) < 10; c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    if (neg) x = -x;
  }
  int T, n, m, a[N][N], s[N][N], c[N], b[N], tmp[N];
  char t[N][N];
  int main() {
    read(T);
    while (T--) {
      int ans;
      read(n);
      read(m);
      ans = n * m;
      for (int i = 0, i_end = n; i < i_end; ++i) scanf("%s", t[i]);
      for (int i = 0, i_end = n; i < i_end; ++i)
        for (int j = 0, j_end = m; j < j_end; ++j) a[i][j] = t[i][j] - '0';
      for (int i = 0, i_end = n; i < i_end; ++i)
        for (int j = 0, j_end = m; j < j_end; ++j)
          s[i][j + 1] = s[i][j] + a[i][j];
      for (int i = 0, i_end = m; i < i_end; ++i)
        for (int j = i + 3, j_end = m; j < j_end; ++j) {
          int sum = 0, mink = -1, all = 0;
          for (int k = 0, k_end = n; k < k_end; ++k)
            c[k] = s[k][j] - s[k][i + 1] + 1 - a[k][i] + 1 - a[k][j];
          for (int k = 0, k_end = n; k < k_end; ++k)
            b[k] = (j - i - 1) - (s[k][j] - s[k][i + 1]);
          for (int k = n - 1; ~k; --k) {
            if (k + 4 < n) {
              int kk = k + 4;
              sum -= c[kk];
              tmp[kk] = sum + b[kk];
              if (!~mink || tmp[mink] > tmp[kk]) mink = kk;
            }
            if (~mink) ans = min(ans, all + b[k] + tmp[mink]);
            all += c[k];
          }
        }
      printf("%d\n", ans);
    }
    return 0;
  }
  