zoukankan      html  css  js  c++  java
  • AcWing95. 费解的开关 枚举+位运算

    这道题的确比较难想,首先我们知道图比较小,有可能是枚举,那么该如何枚举呢???

    你可以发现,我们只要把第一排定了,并且保证第一排不准动,那么答案就定了

    也就是说,我们首先用二进制枚举,枚举第一行需要翻转的,然后让第一行不准再翻转,后面的翻转只能在第二行进行,那么第二翻转的实际上是定好了的,然后因为定好了,所以不能翻转,那么第二行也定了,我们要改变第二行,只能通过第三行,最后判断一下最后一位是不是0就好了,做法的话,可以把每一行用一个数字保存,然后进行异或操作,对某位的1或者0进行操作,或者笨一点开二维数组。

    #include <bits/stdc++.h>
    using namespace std;
    char str[10][10];
    const int INF = 0x3f3f3f3f;
    int main(){
        int t;
        scanf("%d",&t);
        char s[10][10];
        int a[5];
        while(t--){
            memset(a,0,sizeof(a));
            for (int i=0;i<5;i++){
                scanf("%s",s[i]);
                int ss=16;
                for (int j=0;j<5;j++){
                    if (s[i][j]=='0'){
                        a[i]+=ss;
                    }
                    ss=ss/2;
                }
            }
            int b[5];
            int ans=INF;
            for (int i=0;i<(1<<5)-1;i++){
                for (int j=0;j<5;j++){
                   b[j]=a[j];
                }
                int cnt=0;
                for (int j=0;j<5;j++){
                    if((i>>j)&1){
                        cnt++;
                       b[0]=b[0]^(1<<j);
                       b[1]=b[1]^(1<<j);
                       if (j+1<5){
                           b[0]=b[0]^(1<<(j+1));
                       }
                       if (j-1>=0){
                           b[0]=b[0]^(1<<(j-1));
                       }
                    }
                }
                for (int j=1;j<5;j++){
                    for (int k=0;k<5;k++){
                        if((b[j-1]>>k)&1){
                            b[j-1]=b[j-1]^(1<<k);
                            b[j]=b[j]^(1<<k);
                            cnt++;
                            if (k+1<5){
                                b[j]=b[j]^(1<<(k+1));
                            }
                            if (k-1>=0){
                                b[j]=b[j]^(1<<(k-1));
                            }
                            if (j+1<5){
                                b[j+1]=b[j+1]^(1<<(k));
                            }
                        }
                    }
                }
                int flag=0;
                for (int j=0;j<5;j++){
                    if (b[j]!=0){
                        flag=1;
                        break;
                    }
                }
                if (flag==0){
                    ans=min(ans,cnt);
                }
            }
            if (ans<=6){
                printf("%d
    ",ans);
            }else {
                printf("-1
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    按升序合并如下两个list, 并去除重复的元素
    python数据结构
    驼峰式命名改下划线命名
    求某个数出现的次数超过了总数的一半
    翻转字符串
    复习
    RESTful
    Flask wtforms
    数据库连接池(DBUtils)
    iOS
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/12057432.html
Copyright © 2011-2022 走看看