Sajam(01翻转 bitset优化)

原题: http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=2283

题意:

n*n的01矩阵,你可以无限次翻转一行或者一列,可以最多翻转k(k<=n)次一个点。问是否可以全部翻转成0。

解析:

k<=n说明至少有一行不会被翻转单个点,或者k=n时每行翻转一个点。那么枚举每一行为那一行,将其他行与之对比(可以翻转后再对比),不同的数量就是需要翻转单个点的数量。因为有列翻转,所以全部行都一样后可以全部变成0。

每一行一个点的情况也很简单,第一行枚举每个位置翻转,判断其他行是否只翻转一个点后与之相同。

不同点的个数用bitset维护。

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

char x[1002];
bitset<1002>B[1002];

int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        B[i].reset();
        scanf("%s",x+1);
        for(int j=1;j<=n;j++){
            if(x[j]=='x')B[i].set(j);
        }
    }
    
    if(k==n){
        for(int i=1;i<=n;i++){
            int can=1;
            if(i-1)B[1].flip(i-1);
            B[1].flip(i);
            for(int j=2;j<=n;j++){
                B[0]=B[1]^B[j];
                int sub=B[0].count();
                if(sub!=1&&n-sub!=1){can=0;break;}
            }
            if(can)return 0*printf("DA\n");
        }
        B[1].flip(n);
    }
    
    
    int ans=1e9;
    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=1;j<=n;j++){
            if(i==j)continue;
            B[0]=B[i]^B[j];
            int sub=B[0].count();
            sub=min(sub,n-sub);
            sum+=sub;
        }
        ans=min(ans,sum);
    }
    if(ans<=k)printf("DA\n");
    else printf("NE\n");
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/88794510