费解的开关(模拟+二进制+思维)

题目链接: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;
}

 

  

 

posted @ 2020-07-19 14:16  ACM-Epoch  阅读(219)  评论(0编辑  收藏  举报