P5427 [USACO19OPEN]Left Out bitset优化做01矩阵翻转

题目链接:https://www.luogu.org/problemnew/show/P5427

 

题意:

       给你一个L和R组成的n*n的矩阵(可以类比为01矩阵),问你能不能找到这样一个位置,先将它翻转之后,对剩下的矩阵翻转任意行或者任意列,可以使得所有的格子都为0或者1

做法:

       之前做过一道类似的题目还会更难一点,这里的话用到了bitset优化,以某一行i作为一个标准去异或其他所有行,如果异或行j出来的值val取min(val,n-val),就是将行j变到和行i完全相似或者相反需要变的最少的点数。如果能找到这样一行使得和其他行得到的异或和为1,那么就找到了答案,即只有一行有1的贡献,那么就可以找这个行上的所有列,如果val等于1就去找这两行上的不同值,如果val为n-1就去找这两行相同的值即可。(这样做的话和最小的x和y其实并没有什么关系)


#include
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]=='R')B[i].set(j);
        }
    }

    int ansx=-1,ansy=-1,flag=0;
    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;
        }
        if(sum==1){
            for(int j=1;j<=n;j++){
                if(i==j)continue;
                B[0]=B[i]^B[j];
                int sub=B[0].count();
                if(sub==1){
                    for(int k=1;k<=n;k++){
                        if(B[i][k]!=B[j][k]){
                            ansx=j,ansy=k;
                            flag=1;break;
                        }
                    }
                }
                else if(n-sub==1){
                    for(int k=1;k<=n;k++){
                        if(B[i][k]==B[j][k]){
                            ansx=j,ansy=k;
                            flag=1;break;
                        }
                    }
                }
                if(flag) break;
            }
        }
    }
    if(flag==0) printf("-1\n");
    else printf("%d %d\n",ansx,ansy);
}

 

你可能感兴趣的:(数据结构,思维)