CodeForces 425B Sereja and Table
版权声明:本文为博主原创文章,未经博主同意不得转载。
https://blog.csdn.net/u013351160/article/details/37913651
题意:
一个充满0和1的矩形 最多将k个数字翻转 问 最少翻转几个数字能够使全部0或1的连通块都是矩形 假设不可能输出-1
思路:
首先 假设确定了一行 那么整个矩形就确定了
由于在最后的状态中 每一行要么与确定的行全然一致 要么全然相反 这才干保证连通块都是矩形
然后 本题k非常小 因此能够分类讨论
假设 max(n,m)<=k 那么能够暴力枚举第一行状态 进而计算翻转次数 最多仅仅有2^10种情况
否则 max(n,m)>k 那么至少有一行或者一列是没有被改动的 那么能够枚举哪一行没被改动 再计算翻转次数
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 110
int a[N][N];
int n,m,t,tmp,ans,sum;
int main()
{
int i,j,k;
scanf("%d%d%d",&n,&m,&t);
for(i=1;i<=n;i++) for(j=1;j<=m;j++) scanf("%d",&a[i][j]);
if(n<m)
{
for(i=1;i<=m;i++)
{
for(j=i+1;j<=m;j++) swap(a[i][j],a[j][i]);
}
swap(n,m);
}
/*
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) printf("%d ",a[i][j]);
puts("");
}
*/
ans=t+1;
if(n<=t)
{
for(i=0;i<(1<<m);i++)
{
sum=0;
for(k=1;k<=n;k++)
{
tmp=0;
for(j=0;j<m;j++)
{
if(i&(1<<j))
{
if(!a[k][j+1]) tmp++;
}
else
{
if(a[k][j+1]) tmp++;
}
}
sum+=min(tmp,m-tmp);
}
ans=min(ans,sum);
}
}
else
{
for(i=1;i<=n;i++)
{
sum=0;
for(k=1;k<=n;k++)
{
tmp=0;
for(j=1;j<=m;j++)
{
if(a[k][j]!=a[i][j]) tmp++;
}
sum+=min(tmp,m-tmp);
}
ans=min(ans,sum);
}
}
if(ans>t) printf("-1\n");
else printf("%d\n",ans);
return 0;
}
posted on 2019-05-12 15:30 xfgnongmin 阅读(90) 评论(0) 编辑 收藏 举报