枚举

费解的开关

https://ac.nowcoder.com/acm/problem/50920

思路:首先用枚举第一行的按开关情况,一共有32种情况(00000-11111),分别计算出这些情况按开关后亮灭情况
再通过改变第二行的将第一行的灯全亮,以此类推通过改变第三行使第二行全亮,改变第四行使第三行全亮,改变第五行使第四行全亮。
最后更新最小按灯数。

由于只有25个灯,int的有效范围是32位,故我们可以用int中的25位表示灯的情况。
为了表示方便我们将第一行第一个用0位表示,如下所示为五行灯对应int中的位数
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24

为了满足上述对应,我们应该从后往前逐步更新便可以得到最开始的灯的情况g

    for(int i=4;i>=0;i--)
    {
        for(int j=4;j>=0;j--)
        {
            if(a[i][j]=='1') g=(g<<1)+1;
            else g=g<<1;
        }
    }

接着我们枚举第一行的按灯情况00000-11111
对于安灯情况的变化,我们采用change函数完成
void change(int x,int& y)
{
y^=(1<<x);
if(x%5!=4) y^=(1<<(x+1));
if(x%5!=0) y^=(1<<(x-1));
if(x>4) y^=(1<<(x-5));
if(x<20) y^=(1<<(x+5));
}
由上面每个灯对应数字中的位数可以知道,当位数%5!=4时即不是最后一位,其右相邻的一位会转变,
当x%5!=0即不是每行首位时,其左相邻一位转变,当不是第一行时候,其前一行对应位置转变,不是最后一行,
其后一行位置转变。

进行完第一行枚举的转变后,从第一行开始扫描,如果发现没有亮的灯,利用第二行的转变使第一行的该位置灯变亮,以此类推,当前4行全亮后,判断第五行是不是全亮,是的话可以进行一次跟新。

#include<bits/stdc++.h>
using namespace std;
int n;
string a[10];
int minz=1e9;
void change(int x,int& y)//安灯
{
    y^=(1<<x);
    if(x%5!=4) y^=(1<<(x+1));
    if(x%5!=0) y^=(1<<(x-1));
    if(x>4) y^=(1<<(x-5));
    if(x<20) y^=(1<<(x+5)); 
}
void solve(int ch,int staus)
{
    int cnt=0;
    for(int i=0;i<5;i++)
    {
        if((ch>>i)&1)
        {
            cnt++;
            change(i,staus);
        }
    }
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<5;j++)
        {
            int v=i*5+j;//计算出该灯对应的位置
            if(((staus>>v)&1)==0)//发现灭的灯
            {
                cnt++;
                change((i+1)*5+j,staus);//因为利用下一行对应位置使该位置转变,故+5
            }
        }
    }
    if((staus>>20)==31) minz=min(minz,cnt);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    while(n--)
    {
        minz=1e9;
        for(int i=0;i<5;i++)
        {
            cin>>a[i];
        }
        int g=0;
        for(int i=4;i>=0;i--)
        {
            for(int j=4;j>=0;j--)
            {
                if(a[i][j]=='1') g=(g<<1)+1;
                else g=g<<1;
            }
        }
        for(int i=0;i<32;i++)
        {
            solve(i,g);
        }
        if(minz>6) cout<<"-1"<<endl;
        else cout<<minz<<endl;
    }
} 
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务