AcWing 95. 费解的开关
原题链接
中等
作者:
Anoxia_3
,
2020-08-07 09:27:39
,
所有人可见
,
阅读 368
#include <iostream>
#include <cstring>
using namespace std;
const int N = 10;
char g[N][N];
int dx[5] = {0 , -1 , 1 , 0 , 0} , dy[5] = {0 , 0 , 0 , -1 , 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)
g[a][b] = '1' + '0' - g[a][b];
}
}
//1.首先规定:前四行每一个灯的状态由其对应位置下面那个灯来控制;
//2.那么只要第一行的状态确定,为了使每盏灯打开,则要对第二行灯进行操作,那么第二行灯的状态可以确定,以此类推,可以确定前四行,接下来就对
//第五行的状态进行判断,如果第五行不全为1,则当前方案不合理。
//因此只要枚举第一行的每种状态,然后重复上述步骤,即可求出最优值!
//注意:因为只要求枚举到第一行的每种状态即可,因此枚举顺序不重要。
int work()
{
int ans = 0x3f3f3f3f;
for(int k = 0 ; k < 1 << 5 ; k++)//只要将每种状态都枚举到即可,顺序没有关系
{
char backup[10][10];//因为有多种状态,所以要存一个备份
memcpy(backup , g , sizeof g);
int res = 0;//记录最小的步数
for(int j = 0 ; j < 5 ; j++)//每一个k就是一种按的方案,因为只要将每种状态枚举到即可,因此这里k的二进制表示中的1和0表示的
{ //灯的开关,虽然对应的位置不一样,但是不影响结果
if(k >> j & 1)
{
turn(0 , j);
res++;
}
}
for(int i = 0 ; i < 4 ; i++)//因为第1行确定了,后面的操作就确定了,对前四行进行操作
for(int j = 0 ; j < 5 ; j++)
if(g[i][j] == '0') turn(i + 1 , j) , res++;
bool flag = true;
for(int i = 0 ; i < 5 ; i++)//对最后一行进行判断,如果不是全1则说明当前方案不可以
{
if(g[4][i] == '0')
{
flag = false;
break;
}
}
if(flag) ans = min(ans , res);//更新最优值
memcpy(g , backup , sizeof backup);//将原状态还原
}
if(ans > 6) return -1;
return ans;
}
int main()
{
int T;
cin >> T;
while(T--)
{
for(int i = 0 ; i < 5 ; i++) cin >> g[i];
cout << work() << endl;
}
return 0;
}
写的吼啊
3q