费解的开关

费解的开关_第1张图片
费解的开关_第2张图片
费解的开关_第3张图片

本题可通过递推解决。其思路是这样的:由于每按一个灯就会导致上下左右的灯取反,所以如果想让当前某个灯变亮的话,决不能直接按它,而是通过下一行与它同列的灯间接使它变亮。

第i+1行依赖于第 i 行的灯的情况,如果第 i 行是能递推通往正确结果(即全亮)的,那么该行为0的位,应该由第i+1行给调回来。
所以第1行是一切的基础,需要对第一行灯按与不按(而不是亮与不亮)的32中情况逐一枚举,用二进制数k表示,哪一位为1表示要按哪一位

值得注意的是,第一行灯况不是随便的,得满足特定条件,这种情况才能递推为全亮状态。所以,我们需要对第一行的所有灯况进行枚举,通过k就可以不重不漏的组合出所有的按键情况,进而得出所有的灯况。

对第一行的32中灯况逐一递推,如果到第5行时,所有的灯都是亮的,那么这种灯况是合理的,要小心可能有多种灯况都能达到最终全亮的状态,所以需要找到按键次数最少的。

#include 
#include 
#include 
#define INF (~(0x1 << 31))
using namespace std;

int n;
char gra[5][5];
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) {
            gra[a][b] ^= 1;
        }
    }
}
void work(){
    //对第一行的灯按32次即可枚举出所有灯况
    int ans = INF;
    for (int k = 0; k < 1 << 5; k++) {
        int res = 0;
        char backup[5][5];
        memcpy(backup, gra, sizeof gra);//备份
        for(int i = 0; i < 5; i ++) {
            if(k >> i & 1) {
                res ++;
                turn(0, i);
            }
            
        }
        
        //假设第一种情况可以通往最后全1结果
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 5; j++){
                if(gra[i][j] == '0') {
                    res ++;
                    turn(i + 1, j);
                }
            }
        }
        
        //检查最后一行的状态,如果递推成功的话,最后一行应该是全1的
        bool flag = false;
        for (int i = 0; i < 5; i++) {
            if(gra[4][i] == '0') {
                flag = true;
                break;
            }
        }
        memcpy(gra, backup, sizeof backup);//还原
        if(!flag) { //最后一行全为1
           ans = min(res, ans);
        }
        
    }
    if(ans > 6) {
        cout << -1 << endl;
    }else {
        cout << ans << endl;
    }
}
int main(){
    cin >> n;
    for(int k = 0; k < n; k++) {
        for(int i = 0; i < 5; i++) {
            for(int j = 0; j < 5; j++) {
                cin >> gra[i][j];
            }
        }
        work();
    }
    return 0;
}

你可能感兴趣的:(算法竞赛进阶指南)