链接:https://ac.nowcoder.com/acm/contest/998/D
来源:牛客网
费解的开关
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
你玩过“拉灯”游戏吗?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 5n≤5;
对于100%的数据,n≤500n \leq 500n≤500。
输出描述:
输出数据一共有n行,每行有一个小于等于6的整数,它表示对于输入数据中对应的游戏状态最少需要几步才能使所有灯变亮。
对于某一个游戏初始状态,若6步以内无法使所有灯变亮,请输出“-1”。
示例1
输出
复制3 2 -1
这道题我一开始思考的方向错了 就遍历了5x5的格子 分最上面 最下面和中间 找连通块的想法
后来第二个样例输出-1才发现自己想错了
同时这道题我也发现这种01矩阵 cin scanf%d 都是不能把int【】【】输入进去的
要么是字符串输入 边输入边改成int 要么是%1d 但是%1d的效率太低 不可取
然后正确的做法就是枚举出第一排灯的状态 要修改第i行的灯是通过第i+1行等修改得到的
最后检查第五行是否全是1达到满足条件
下面的我的代码
#include<bits/stdc++.h> using namespace std; #define ll long long #define inf 0x3f3f3f3f int n; int a[10][10],b[10][10]; int cnt; int check(int step){ int sum=step; for(int i=1;i<=5;i++){ for(int j=1;j<=5;j++)b[i][j]=a[i][j]; } for(int i=1;i<=4;i++){ for(int j=1;j<=5;j++){ if(!b[i][j]){ b[i][j]^=1; b[i+1][j]^=1; b[i+1][j-1]^=1; b[i+1][j+1]^=1; b[i+2][j]^=1; sum++; } } } for(int i=1;i<=5;i++){ if(!b[5][i])return inf; } return sum; } void dfs(int x,int step){ if(x>5){ cnt=min(cnt,check(step)); return; } a[1][x]^=1; a[1][x-1]^=1; a[1][x+1]^=1; a[2][x]^=1; dfs(x+1,step+1); a[1][x]^=1; a[1][x-1]^=1; a[1][x+1]^=1; a[2][x]^=1; dfs(x+1,step); } int main(){ cin>>n; string s; while(n--){ cnt=inf; for(int i=1;i<=5;i++){ cin>>s; for(int j=0;j<5;j++){ a[i][j+1]=s[j]-'0'; } } dfs(1,0); if(cnt==inf||cnt>6){ printf("-1\n"); } else printf("%d\n",cnt); } }