zoukankan      html  css  js  c++  java
  • AC_95. 费解的开关

    题目描述:

    你玩过“拉灯”游戏吗?25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

    我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。下面这种状态

    10111
    01101
    10111
    10000
    11011
    在改变了最左上角的灯的状态后将变成:

    01111
    11101
    10111
    10000
    11011
    再改变它正中间的灯后状态将变成:

    01111
    11001
    11001
    10100
    11011
    给定一些游戏的初始状态,编写程序判断游戏者是否可能在6步以内使所有的灯都变亮。

    输入格式
    第一行输入正整数n,代表数据中共有n个待解决的游戏初始状态。

    以下若干行数据分为n组,每组数据有5行,每行5个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。

    输出格式
    一共输出n行数据,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。

    对于某一个游戏初始状态,若6步以内无法使所有灯变亮,则输出“-1”。

    数据范围
    0<n≤500
    输入样例:
    3
    00111
    01011
    10001
    11010
    11100

    11101
    11101
    11110
    11111
    11111

    01111
    11111
    11111
    11111
    11111
    输出样例:

    3
    2
    -1

    //算法进阶指南
    /*
    递推与递归
    32*20*5*500 = 160 0000
    */
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define INF 1000;
    
    char g[10][10];
    //方向数组  中上右下左  顺时针方向
    int dx[5] = { 0, -1, 0, 1, 0 }, dy[5] = { 0, 0, 1, 0, -1 };
    
    void turn(int x, int y)//设置开关
    {
        for (int i = 0; i < 5; i++)
        {
            int a = x + dx[i], b = y + dy[i];
            if (a >= 0 && a < 5 & b >= 0 && b < 5)
            {
                g[a][b] = '0'+ ('1'-g[a][b]); //开关变化,1变为0 0变为1  基础是0
    
                //g[a][b] ^= 1; //开关变化,1变为0 0变为1
            }
        }
    }
    
    int work()
    {
        int ans = INF;
        for (int k = 0; k < 32; k++)//
        {
            int res = 0;//记录当前方案数
            char backup[10][10];
            memcpy(backup, g, sizeof g);//备份
            //处理第一行
            for (int j = 0; j < 5; j++)
            {
                if (k >> j & 1)//从前往后过一遍,如果枚举当前的状态是1的话,就需要按一下开关
                {
                    res++;
                    turn(0, j);
                }
            }
            //从前往后 递推前n-1行
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (g[i][j] == '0')//如果那块位置是0,则把它的下一个位置的开关按一下
                    {
                        res++;
                        turn(i+1, j);
                    }
                }
            }
            bool is_successful = true;
            for (int j = 0; j < 5; j++)
            {
                if (g[4][j] == '0')//如果最后一行还有0的话,当前方案不合法
                {
                    is_successful = false;
                    break;
                }
            }
            if (is_successful == true)//如果方案合法,则取出最小值
            {
                ans = min(ans, res);
            }
            memcpy(g, backup, sizeof(g));//每一轮枚举结束之后,恢复记忆数组
        }
        if (ans > 6)//如果方案数目大于6,则不合法
        {
            ans = -1;
        }
        return ans;
    }
    
    int main()
    {
        int N;
        cin >> N;
        while (N--)
        {
            for (int i = 0; i < 5; i++)
                cin >> g[i];//每隔五个一组
            cout << work() << endl;
        }
        return 0;
    }
  • 相关阅读:
    AJAX原生态编写
    oracle中分页查询
    myeclipse 2014 专业版 安装 svn插件
    List.toArray()用法详解
    数据库语句 select * from table where 1=1 的用法和作用
    setObject()用法
    Golang语言学习笔记(十四)
    Golang语言学习笔记(十三)
    Golang语言学习笔记(十二)
    Golang语言学习笔记(十一)
  • 原文地址:https://www.cnblogs.com/gcter/p/11358615.html
Copyright © 2011-2022 走看看