A. Portal (dp optimized enumeration)

Problem - 1580A - Codeforces

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(); 
	}
}

 

Guess you like

Origin blog.csdn.net/m0_64158084/article/details/131478161