CQXYM found a rectangle of size n×m. A rectangle is composed of n rows and m columns of blocks. Each block can be an obsidian block or an empty block. CQXYM can turn obsidian blocks into empty blocks, or empty blocks into obsidian blocks, with one operation.
A rectangle M of size a×b is called a portal if and only if the following conditions are met:
a≥5,b≥4
对于所有1<x<a,方块Mx,1和Mx,b都是黑曜石方块。
对于所有1<x<b,方块M1,x和Ma,x都是黑曜石方块。
对于所有1<x<a,1<y<b,方块Mx,y都是空方块。
M1,1、M1,b、Ma,1、Ma,b可以是任意类型的方块。
Note that the number of rows must be a and the number of columns must be b, not the other way around.
Note that the corner blocks can be of any type.
CQXYM wants to know how many operations he needs to perform at least to make at least one subrectangle a portal.
Input: The first line contains an integer t (t≥1), indicating 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 there are n lines, each containing m characters 0 or 1. If the j-th character in the i-th row is 0, then the square Ai,j is an empty square. Otherwise, block Ai,j is an obsidian block.
Ensure that the sum of n in all test cases does not exceed 400.
Ensure that the sum of m in all test cases does not exceed 400.
Output: Output t answers, each answer occupies one line.
Examples
Input
Copy
1 5 4 1000 0000 0110 0000 0001
Output
Copy
12
Input
Copy
1 9 9 001010001 101110100 000010011 100000001 101010101 110001111 000001111 111100000 000110000
Output
Copy
5
Solution:
The idea that can be thought of is that we enumerate the top, bottom, left and right of the rectangle, but the time complexity of this is O(n^4)
So think about how to optimize out one dimension
Suppose we enumerate the upper and lower bounds, we can use the prefix sum to conveniently and quickly find out how much a column needs to be changed.
Then enumerate column j
Assume that sum is the value that needs to be changed to the current position (except that the boundaries are all 0)
cnt is to the current position, followed by the boundary needs. This column is the value that needs to be changed by the boundary.
Assume i is the left boundary and j is the bounded
sum[j - 1] + cnt[j] - sum[i] + cnt[i], which is what you want
We found that as long as we maintain the minimum value of cnt[i] - sum[i] and optimize one dimension, we no longer need to enumerate the left boundary.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 5e5*2 + 10;
int mod = 998244353;
int a[405][505];
int s[405][405];
int pre[N];
void solve()
{
int n,m;
cin >> n >> m;
for(int i = 1;i <= n;i++)
{
string t;
cin >> t;
t = " " + t;
for(int j = 1;j <= m;j++)
{
a[i][j] = t[j] - '0';
s[i][j] = s[i - 1][j] + a[i][j];
}
}
int ans = 1e9;
pre[0] = 1e9;
for(int i = 1;i <= n;i++)
{
for(int j = i + 4;j <= n;j++)
{
int sum = 0;
for(int k = 1;k <= m;k++)
{
int x = s[j - 1][k] - s[i][k];
int y = 2 - a[i][k] - a[j][k];
int w = j - i - 1 - x;
if(k > 3)
{
ans = min(ans,pre[k - 3] + sum + w);
}
sum += x + y;
pre[k] = min(pre[k - 1],w - sum);
}
}
}
cout << ans <<"\n";
}
signed main()
{
ios::sync_with_stdio(0 );
cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}