费解的开关

链接

是否在6步之内让所有的灯都开着

假设第一行固定,那么通过第二行修改第一行,之后,通过第三行修改第二行(如果第二行为0,在第三行上按一下,变为1)

所以只要枚举第一行的状态即可

时间复杂度 25

*500 * 20

第一行的可能 * 测试样例组数 * 递推数

#include <bits/stdc++.h>
using namespace std;
int n;
char g[10][10];
int dp[5][2] = {{0,0},{0,1},{0,-1},{1,0},{-1,0}};
void handle(int x,int y){
    for(int i = 0; i < 5; i++){
        int dx = x + dp[i][0],dy = y + dp[i][1];
        if(dx >= 0 && dx < 5 && dy >= 0 && dy < 5){
            g[dx][dy] ^= 1;
        }
    }
}
int work(){
    int ans = 1000000;
    for(int i = 0; i < 1 << 5; i++){//枚举所有状态
        char backup[10][10];
        memcpy(backup,g, sizeof g);//先复制一遍
        int res = 0;
        for(int j = 0; j < 5; j++){
            if(i >> j & 1){//如果是1的话,按下去变为0
                res++; handle(0,j);
            }
        }
        for(int k = 0; k < 4; k++){
            for(int j = 0; j < 5; j++){
                if(g[k][j] == '0'){
                    res++;
                    handle(k + 1,j);
                }
            }
        }
        bool flag = true;
        for(int j = 0; j < 5; j++)
            if(g[4][j] == '0') {
                flag = false;
                break;
            }
        if(flag) ans = min(ans,res);
        memcpy(g, backup,sizeof(g));
    }
    if(ans > 6) return -1;
    return ans;
}

int main(){
    //freopen("in","r",stdin);
    ios::sync_with_stdio(0);
    cin >> n;
    while(n--){
        for(int i = 0; i < 5; i++) cin >> g[i];
        cout << work() << endl;
    }
    return 0;
}
View Code

 

posted @ 2020-09-03 16:49  Hazelxcf  阅读(253)  评论(0编辑  收藏  举报