黑白矩阵 题解

image

1<=n,m<=100,1<=k<=10,T<=50

首先这个同色极大连通块都是矩形说明了啥呢?

相邻两行(两列)一定是同色或者反色的。

当n>k时,我们可以发现有一行肯定是不会被修改的,我们枚举那一行统计一下即可。

否则n<=10,那么我们枚举修改完之后某一列的状态,2^n枚举就行了。

这真是一道**题啊。

(下面这段代码的cnt1比较不和谐,可能要修改一下)

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define fi first
#define se second
#define fe first
#define cnt1 __builtin_popcount
int T,n,m,k;
int arr[233][233],orz[233];
bitset<103> bs[233],fbs[233];
void sol()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<n;i++) bs[i]=bitset<103>();
    for(int i=0;i<n;i++) fbs[i]=bitset<103>();
    for(int j=0;j<m;j++) orz[j]=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        scanf("%d",&arr[i][j]), bs[i][j]=arr[i][j], fbs[i][j]=!arr[i][j]
        , orz[j]=orz[j]*2+arr[i][j];
    }
    //乱搞 
    if(n>k)
    {
        int ans=2000000000;
        for(int i=0;i<n;i++)
        {
            int cnt=0;
            for(int j=0;j<n;j++)
            cnt+=min((bs[i]^bs[j]).count(),(bs[i]^fbs[j]).count());
            ans=min(ans,cnt);
        }
        if(ans>k) puts("-1");
        else printf("%d
",ans);
        return;
    }
    int ans=2000000000;
    for(int i=0;i<(1<<n);i++)
    {
        int cnt=0;
        for(int j=0;j<m;j++)
        cnt+=min(cnt1(orz[j]^i),cnt1(orz[j]^i^((1<<n)-1)));
        ans=min(ans,cnt);
    }
    if(ans>k) puts("-1");
    else printf("%d
",ans);
}
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
int main()
{
    FO(table)
    scanf("%d",&T);
    while(T--) sol();
}
原文地址:https://www.cnblogs.com/zzqsblog/p/5721428.html