每日一题——费解的开关

题目

费解的开关

题解

将第一层的状态确定下来,第二层就能确定,同理到最后一层也就确定了,所以只需要枚举第一层所有状态就可以确定步数,满足条件就存下步数,比较并选取最小步数,最后如果步数大于6输出-1。对于翻转操作,dx、dy可以很方便得对周围方格进行枚举,别忘了每枚举完第一层一个状态需要恢复到题目所给的状态。memcpy就是复制操作,backup这个数组就是保存备份初始状态。

参考代码

#include<iostream>
#include<cstring>
using namespace std;
const int N = 10, INF = 0x3f3f3f3f;
int T;
int dx[]={0,-1,0,1,0};
int dy[]={0,0,1,0,-1};
char g[N][N],backup[N][N];
void turn(int x, int y){
    for(int i = 0; i < 5; i ++){
        int xx = x + dx[i], yy = y + dy[i];
        if(xx >= 0 && xx <=4 && yy >= 0 && yy <=4) g[xx][yy] ^= 1;
    }
}
int work(){
    int res = INF;
    memcpy(backup, g, sizeof g);
    for(int k = 0; k < 1 << 5; k ++){
        int temp = 0;
        for(int j = 0; j < 5; j ++){
            if((k >> j) & 1) turn(0, j),temp++;
        }
        for(int i = 0; i < 4; i ++){
            for(int j = 0; j < 5; j++){
                if(g[i][j] == '0') turn(i + 1, j),temp++;
            }
        }
        bool is_flag = true;
        for(int i = 0; i < 5; i ++)
            if(g[4][i] == '0'){
                is_flag = false;
                break;
            }
        if(is_flag) res = min(res, temp);
        memcpy(g,backup,sizeof g);
    }
    if(res > 6) res = -1;
    return res;
}
int main(){
    cin >> T;
    while(T --){
        for(int i = 0; i < 5; i ++) cin >> g[i];
        cout << work() << endl;
    }
    return 0;
}
posted @ 2025-03-05 21:04  PZnwbh  阅读(28)  评论(0)    收藏  举报