zoukankan      html  css  js  c++  java
  • 费解的开关(模拟+二进制+思维)

    题目链接:https://ac.nowcoder.com/acm/contest/998/D

    题意:就是给出t组询问数据,然后每一组数据给出一个5*5的矩阵,矩阵元素是由0、1构成,并且每一次按动一个元素会导致其上下左右与自身共计5个位置的元素发生改变,即0<->1,闲现在请问你能否再6步之内将所有的0都变为1。

    思路:我们通过观察,发现既然每按动一个按钮都会导致周围五个按钮状态发生变化,不难想到判断第i排是否为0,若为0我们就通过按第i+1排的按钮来改变第i排按钮的状态,并且通过这样的操作,将第i排的状态就永远固定为1了,(因为下一次是判断第i+1排,通过改变第i+2排,而第i+2排的改变并不会影响到第i排按钮状态),最后通过判断最后一排是否全部为1来判断方案是否可行。

    技巧:

      1.通过二进制枚举第一排的操作可能,还是与之前的二进制思想相同,判断位数是否为1来进行操作。因为通过枚举二进制数,是可以枚举完所有的可能性的,因为比如有n个按钮,那么其操作方案数就是2n种,而区间[0,1 << n)刚好就是包含了所有可能性。

      2.每一次枚举第一排的操作方案,都要先将初始情况保存,再进行完操作之后,再恢复初始状态,运用memcpy(a,b,sizeof(b))可以快速完成这一操作。

      3.每一次按动开关进行操作,都需要对步数递增,最终通过最小步数判断答案是否符合要求。

    做题代码技巧:先布局,再写具体的实现函数。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 10000005;
    
    char s[10][10];
    int dix[5] = {0, -1, 1, 0, 0};
    int diy[5] = {0, 0, 0, 1, -1};
    
    void turn(int a, int b)
    {
        for(int i = 0; i < 5; i++)
        {
            int x = a + dix[i];
            int y = b + diy[i];
            if(x >= 0 && x < 5 && y >= 0 && y < 5)  s[x][y] ^= 1;
        }
    }
    
    int work()
    {
        int ans = INF;
        for(int k = 0; k < 1 << 5; k++)
        {
            int res = 0;
            char backup[10][10];
            memcpy(backup, s, sizeof(s));
            for(int i = 0; i < 5; i++)
                if(k >> i & 1)
                {
                    res ++;
                    turn(0, i);
                }
            for(int i = 0; i < 4; i++)
                for(int j = 0; j < 5; j++)
                    if(s[i][j] == '0')
                    {
                        turn(i + 1, j);
                        res++;
                    }
            bool is_ok = true;
            for(int i = 0; i < 5; i++)
                if(s[4][i] == '0')
                {
                    is_ok = false;
                    break;
                }
            if(is_ok)   ans = min(ans, res);
            memcpy(s, backup, sizeof(s));
        }
        return ans > 6 ? -1 : ans;
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int t;  cin >> t;
        while(t--)
        {
            for(int i = 0; i < 5; i++)  cin >> s[i];
            cout << work() << endl; 
        }
        return 0;
    }
    

      

  • 相关阅读:
    docker下overlay2占用空间过大,清理docker占用空间
    js为浏览器URL追加参数
    img转Blob对象
    《ECharts》伪立体柱状图
    js分秒格式转时分秒
    表单边框缺一角效果
    File对象转base64
    《VUE》可编辑div限制字数
    quill富文本编辑器自定义字体、文字大小(编辑器内含element上传组件)
    我在华为工作十年的感悟(文摘)
  • 原文地址:https://www.cnblogs.com/ACM-Epoch/p/13339574.html
Copyright © 2011-2022 走看看