CF1580A Portal

Portal

给一个01矩阵,求一个需要修改次数最小的子矩阵(长度至少为4,高度至少为5)的修改次数。
一次修改可以把单个0改为1或者1改为0。
修改后的矩阵需满足,中间全为0,四边为1,四个角随意。

枚举子矩阵的上下界和右边界,左边界动态维护。
f[k]:以i,j为上下界,k为右边界的修改次数。(不考虑右边界)
f [ k ] = m i n ( f [ k − 1 ] + 加 入 第 k 行 需 要 的 修 改 次 数 , 以 i 、 j 、 k − 3 、 k 为 边 界 的 矩 阵 的 修 改 次 数 ) f[k]=min(f[k-1]+加入第k行需要的修改次数,以i、j、k-3、k为边界的矩阵的修改次数) f[k]=min(f[k1]+kijk3k)
每次用当前的 f [ k ] f[k] f[k]+右边界需要的修改次数更新ans。

#include<bits/stdc++.h>
using namespace std;

#define read(a) scanf("%d",&a)
#define maxn 400

int n,m;
int r[maxn+5][maxn+5];
int a[maxn+5][maxn+5],b[maxn+5][maxn+5]; //a:1  b:0
int f[maxn+5];

int find1(int i,int j,int k) {
	return a[j][k]-a[i-1][k];
}

int find0(int i,int j,int k) {
	return b[j][k]-b[i-1][k];
}

int main() {

	int T;
	read(T);
	
	while(T--) {
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		
		read(n),read(m);
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++) {
				char x;
				do{x=getchar();}while(x!='0'&&x!='1');
				r[i][j]=x-'0';
				a[i][j]=r[i][j]+a[i-1][j];
				b[i][j]=1-r[i][j]+b[i-1][j];
			}
		}
		
		int ans=(int)1e9;
		for(int i=1;i<=n;i++) {
			for(int j=i+4;j<=n;j++) {
				f[3]=(int)1e9;
				for(int k=4;k<=m;k++) {
					int x=find0(i+1,j-1,k-3)+!r[i][k-2]+!r[i][k-1]+!r[j][k-2]+!r[j][k-1]+find1(i+1,j-1,k-2)+find1(i+1,j-1,k-1);
					f[k]=min(f[k-1]+find1(i+1,j-1,k-1)+!r[i][k-1]+!r[j][k-1],x);
					ans=min(ans,f[k]+find0(i+1,j-1,k));
				} 
			}
		}
		
		printf("%d\n",ans);
	}
	
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值