• [算法竞赛进阶指南] 0x02 D.费解的开关


    题目链接

    题目描述

    你玩过“拉灯”游戏吗?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个字符。每组数据描述了一个游戏的初始状态。各组数据间用一个空行分隔。
    对于30%的数据,n≤5n leq 5n5;
    对于100%的数据,n≤500n leq 500n500。

    输出描述:

    输出数据一共有n行,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
    对于某一个游戏初始状态,若6步以内无法使所有灯变亮,请输出“-1”。

    输入

    3
    00111
    01011
    10001
    11010
    11100
    
    11101
    11101
    11110
    11111
    11111
    
    01111
    11111
    11111
    11111
    11111

    输出

    3
    2
    -1

    思路:
    1、只有25个点,每个点只有开或关两种状态,那么可以用二进制1代表开,0代表关,那么我们就可以用一个整数来代表这个图的状态了。
    2、我们可以逆向出发,从每个点全开着的情况出发,bfs搜到超过6步为止。对于每一个第一次碰到的状态,我们记录下到这个状态的步数,即这个状态的答案。
    3、预处理结束后,根据给的状态一一作答。

    代码:
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 6;
     4 queue <int> q;
     5 map <int, int> mp;
     6 int T;
     7 
     8 inline int filp(int stat, int i)
     9 {
    10     stat ^= 1 << i;
    11     if (i % 5 != 4) stat ^= 1 << i+1;
    12     if (i % 5) stat ^= 1 << i-1;
    13     if (i / 5) stat ^= 1 << i-5;
    14     if (i / 5 != 4) stat ^= 1 << i+5;
    15     return stat;
    16 }
    17 
    18 inline void bfs()
    19 {
    20     q.push((1<<25)-1), mp[(1<<25)-1] = 1;
    21     while (!q.empty()) {
    22         int x = q.front();
    23         q.pop();
    24         if (mp[x] == 7) return;
    25         for (int i=0;i<25;i++) {
    26             int nx = filp(x, i);
    27             if (mp[nx] == 0) mp[nx] = mp[x] + 1, q.push(nx);
    28         }
    29     }
    30 }
    31 
    32 int main()
    33 {
    34     bfs();
    35     cin >> T;
    36     while (T--) {
    37         int now = 0;
    38         for (int i=0;i<25;i++) {
    39             int c; scanf("%1d", &c);
    40             now += (c << i);
    41         }
    42         cout << mp[now] - 1 << endl;
    43     }
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    汉字乱码、加密后结果字符串不一致
    msgpack和TParams互相转换
    unigui监听会话开始和结束
    System.JSON.Builders.pas
    保证最终一致性的模式
    使用 Delta Sharing 协议进行数据共享
    dremio 16 升级问题
    graylog 4.0 运行
    supabase 开源firebase 可选工具
    cube.js 最新playground 说明
  • 原文地址:https://www.cnblogs.com/FantaDevourer/p/12939011.html
Copyright © 2020-2023  润新知