本题不适用于递推,因为前几个题中一个开关可以只由一个开关来改变它的状态(上面的状态可以由下面改变 如:费解的开关),但本题中上面的开关状态可以由下面任意一个开关改变。
思维:把所有的情况都列举出来,因为本题可以暴力,时间复杂度小于1亿
vector容器的代码会使运行时间多3倍(拿y总的代码和自己的进行了对比,亲测)
学会使用memcpy和sizeof
#include <cstring>//因为y总用的vector容器,我将他的代码进行了改变,蓝桥杯vector会有警告
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 5;
char g[N][N], backup[N][N];
int back[25][N];//back用于输出最后答案,每次发现步数少到都会复制到back中
int get(int x, int y)
{
return x * 4 + y;//将二维数组转换为一维,进行二进制操作 (与48行对应)
}
void turn_one(int x, int y)
{
if (g[x][y] == '+') g[x][y] = '-';//符号转化
else g[x][y] = '+';
}
void turn_all(int x, int y)
{
for (int i = 0; i < 4; i ++ )
{
turn_one(x, i);
turn_one(i, y);
}
turn_one(x, y);
}
int main()
{
for (int i = 0; i < 4; i ++ ) cin >> g[i];
int cnt=0;
for (int op = 0; op < 1 << 16; op ++ )// 1 << 16 表示为2的16次方
{
int ans[25][N],k=0;
memcpy(backup, g, sizeof g); // 将g备份
// 进行操作
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
if (op >> get(i, j) & 1)//当二进制的位数为1时,需要操作
{
ans[k][0]=i;
ans[k++][1]=j;
turn_all(i, j);
}
// 判断所有灯泡是否全亮
bool has_closed = false;
for (int i = 0; i < 4; i ++ )
for (int j = 0; j < 4; j ++ )
if (g[i][j] == '+')
has_closed = true;
if (has_closed == false)
{
if (cnt==0 || cnt > k) {
//当前的移动步数小于cnt时,将k赋值给cnt
cnt = k;
memcpy(back, ans, sizeof ans); //将ans数组复制给back
}
}
memcpy(g, backup, sizeof g); // 还原g数组
}
cout << cnt << endl;
for(int i=0;i<cnt;i++)
{
printf("%d %d\n",back[i][0]+1,back[i][1]+1);//数组需要加一(你懂!)
}
return 0;
}