题意:
对于给出的矩阵,选择一个整数k,为了使每个k*k正方形里的数字全为1或者全为0,你需要变换某些不一样的数字,求变换的最少次数。当n或者m不能整除k时,可以延长到整除为止,延长部分数字为0;注意是最少次数,所以要找到最合适的k。
思路:
先打表,算出每个位置所包含的数字1的数目,之后在计算每个方块的数字时,只需要用相减的方法就可以算出来,不用再遍历。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char ma[5005][5005];
int biao[5005][5005];
int n,m,k,co,mi=100000000;
void yu(){
for(int i=1;i<=5000;i++)
for(int j=1;j<=5000;j++)
if(ma[i][j]=='1') biao[i][j]=biao[i][j-1]+1;
else biao[i][j]=biao[i][j-1];
for(int j=1;j<=5000;j++)
for(int i=1;i<5000;i++)
biao[i][j]=biao[i][j]+biao[i-1][j];
}
int sea(int dx,int dy){
for(int k=2;k<=max(dx,dy);k++){
co = 0;
for(int i=k;i-k< dx;i+=k)
for(int j=k;j-k<dy;j+=k){
int temp=biao[i][j]-biao[i-k][j]-biao[i][j-k]+biao[i-k][j-k];
co+=min(temp,k*k-temp);
}
if (co<mi)
mi=co;
}
return mi;
}
int main(){
scanf("%d %d",&n,&m);
memset(biao,0,sizeof(biao));
memset(ma,0,sizeof(ma));
for(int i=1;i<=n;i++)
scanf("%s",ma[i]+1);
yu();
printf("%d\n",sea(n,m));
return 0;
}