AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
    • 吐槽
  • App
  • 登录/注册

AcWing 95. 费解的开关    原题链接    中等

作者: 作者的头像   那必须得是我了 ,  2022-03-20 15:49:11 ,  所有人可见 ,  阅读 98


0


AC95. 费解的开关
题目描述
25盏灯排成一个5x5的方形。每一个灯都有一个开关,游戏者可以改变它的状态。每一步,游戏者可以改变某一个灯的状态。游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。

我们用数字“1”表示一盏开着的灯,用数字“0”表示关着的灯。


总体思路为,答案的情况完全取决于第一行的情况,因此具体操作为(见“疑惑”)当第一行情况决定后,对每盏灭着的灯都进行点亮操作由下面的灯进行点亮(因为对当前灯的反转也会将周围的灯反转),枚举完n-1行,对最后一行进行判断灯是否全亮,因为对最后一行的操作会影响到上一行,所以枚举最后一行的时候上面的灯是全亮着的,如果最后一行存在灭着的灯则这种解不存在。

疑惑:一开始没想清楚为什么要用op枚举所有情况,实际上op代表的是对于第一行每个元素按与不按的两种操作,并非重新生成了一种情况。倘若op等于1(00001),则代表着对第1行(数组下标为0)的第2个元素进行反转操作g[0][1]。由于下一行是否反转取决于上一行,因此第一行的是否反转已经确定了结果(第一行的操作完全确定了答案)。而由于第一行有五个元素,每个元素都有按或不按两种情况,因此所有情况为2^5=32,也就是从00000(对第一行的台灯全部不进行反转操作)到11111(对第一行的情况全部操作)。对所有操作枚举一遍的结果取min即可得出最小值。
如果从第二行开始枚举,实际上情况只有一种,也就是第一行情况已经确定了,第二行的情况也就确定了,只有一个值。达不到最优的效果。


以下为代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 6;

char g[N][N], backup[N][N];
int dx[5] = {-1, 0, 1, 0, 0}, dy[5] = {0, 1, 0, -1, 0};

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 || b<0 || a>4 || b>4)//超出边界
            continue;
        g[a][b]^=1;//该操作为将字符'0'与'1'反转
    }
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        for(int i=0;i<5;i++)    cin>>g[i];

        int res=10;
        for(int op=0;op<32;op++)
        {
            memcpy(backup,g,sizeof g);//对g进行备份,下一轮需要用
            int step=0;
            for(int i=0;i<5;i++)
            {
                if(op>>i&1)//对第一行的操作
                {
                    step++;
                    turn(0,i);
                }
            }
            for(int i=0;i<4;i++)
            {
                for(int j=0;j<5;j++)
                {
                    if(g[i][j]=='0')
                    {
                        turn(i+1,j);
                        step++;
                    }
                }
            }
            bool dark=false;
            for(int i=0;i<5;i++)
            {
                if(g[4][i]=='0')
                {
                    dark = true;
                    break;
                }
            }
            if(!dark)   res=min(step,res);
            memcpy(g,backup,sizeof g);
        }
        if(res>6)   res=-1;
        cout<<res<<endl;
    }
    return 0;
}

0 评论

你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息