• 费解的开关【DFS】【模拟】


    题目大意:

    给出n5×5的开关,按下一个开关会影响周围4个灯和自己(开变成关,关变成开)。求最少需要按多少次开关才能使得全部灯变亮?(6次以上则视为无法点亮)。


    思路:

    这道题如果用普通的广搜会T。。。
    这道题的正解如下:
    假设我们不动第一行的开关,那么如果要改变第一行的灯的状态,那么就只能更改第二行的位于该灯下面的那个开关来改变。例如:
    这里写图片描述
    如果我们固定了第一行,那么为了将全部都变成绿色,就必须利用第二行。例如,(1,1)是红色,为了让它变成绿色,就必须更改(2,1)。为了让(1,4)变成绿色,就必须更改(2,4)
    更改后图形如下:
    这里写图片描述
    那么我们再固定第二行,利用第三行来更改它(就像用第一行来更改第二行一样),就变成了
    这里写图片描述
    同理,更改第三行
    这里写图片描述
    再更改第四行
    这里写图片描述
    这是我们发现,最后还有一个灯是关着的,所以,这说明第一行的灯如果是这样的情况就无法成立
    那么就枚举第一行的点击方式,再继续按照刚才的方法,判断能否点玩即可。


    代码:

    #include <cstdio>
    #include <iostream>
    #define Inf 1e7
    using namespace std;
    
    int n,a[6][6],b[6][6],ans;
    
    int check(int x)  //判断当第一行的情况是否成立
    {
        int sum=x;
        for (int i=1;i<=5;i++)
         for (int j=1;j<=5;j++)
          b[i][j]=a[i][j];
        for (int i=1;i<=4;i++)
         for (int j=1;j<=5;j++)
          if (!b[i][j])  //第i行是关灯
          {
             sum++;  //记录次数
             b[i][j]=1-b[i][j];
             b[i+1][j]=1-b[i+1][j];
             b[i+1][j-1]=1-b[i+1][j-1];
             b[i+1][j+1]=1-b[i+1][j+1];
             b[i+2][j]=1-b[i+2][j];
          }
        for (int i=1;i<=5;i++)
         if (!b[5][i]) return Inf;  //判断最后一行是否全开
        return sum;
    }
    
    void dfs(int x,int k)  //枚举第一行的情况
    {
        if (x>5)  //第一行更改完毕
        {
            ans=min(ans,check(k));
            return;
        }
        a[1][x]=1-a[1][x];
        a[1][x-1]=1-a[1][x-1];
        a[1][x+1]=1-a[1][x+1];
        a[2][x]=1-a[2][x];
        dfs(x+1,k+1);  //按这个开关
        a[1][x]=1-a[1][x];
        a[1][x-1]=1-a[1][x-1];
        a[1][x+1]=1-a[1][x+1];
        a[2][x]=1-a[2][x];
        dfs(x+1,k);  //不按这个开关
        return;
    }
    
    int main()
    {
        scanf("%d",&n);
        while (n--)
        {
            for (int i=1;i<=5;i++)
             for (int j=1;j<=5;j++)
              scanf("%1d",&a[i][j]);
            ans=Inf;
            dfs(1,0);
            if (ans<7) printf("%d\n",ans);
             else printf("-1\n");
        }
        return 0;
    }
  • 相关阅读:
    可翻页查看(more、less)
    在CentOS 6.0下面永久关闭SELinux和防火墙
    Linux(CentOS 6.4)设置VNC远程桌面连接
    CentOS Linux防火墙配置及关闭
    ubuntu12.04循环登录,无法进桌面的问题
    转载 vi替换windows换行符为linux换行符
    sublime忽略打开工程中某些文件夹,不在搜索之列
    erl_0021 erlang和java的内存模型比较(引用)
    erl_0020 《面对软件错误构建可靠的分布式系统》读书笔记001 “面向并发COPL”
    erl_0019《硝烟中的erlang》 读书笔记005 “进程信息"
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998782.html
Copyright © 2020-2023  润新知