#include<iostream>
#include<vector>
#include<string>
#include<queue>
/**
* 哇偶。。。。。一遍过。。。。真是太不习惯了
* 本题相当于poj1753的进阶版,可以先完成poj1753,再来尝试这题
*/
/**
* @note 题意:
有一冰箱,上面4x4共16个开关("-"状态表示open,"+"状态表close),
当改变一个开关状态时,该开关所在行、列的全部开关状态也会同时改变。
给出一个开关状态,问从该状态开始,使得所有开关打开(全"-"),
至少需要操作多少步,并把操作过程打印出来(打印所操作开关的行列坐标,坐标从1开始)
思路:主要是理解操作之间的不相关性,即操作间顺序的不相关(操作(1,1)->操作(2,2)等效于操作(2,2)->操作(1,1)),
和操作次数的不相关(对同一个开关操作0次等效于操作2次)
*/
using namespace std;
int state[][4] = { { 8,4,2,1 },{ 15,15,15,15 } };
///field数组储存开关信息用int中的前四位来表示开关的一行,1表示打开,op储存操作信息
struct my_data
{
int field[6];
bool op[5][5];
};
///读取数据
void read(int field[6])
{
for (int i = 1; i <= 4; i++)
{
for (int j = 1; j <= 4; j++)
{
field[i] <<= 1;
char temp;
cin >> temp;
if (temp=='-')
{
field[i] |= 1;
}
}
}
}
///依题意规则翻转开关
void flip(int i, int j,my_data &data)
{
--j;
for (size_t temp = 1; temp <=4 ; temp++)
{
if (temp!=i)
{
data.field[temp] ^= state[0][j];
}
}
data.field[i] ^= state[1][j];
}
/**
* @param n:还可以最多翻转开关的数量
* i:正在检测开关的行数 j:列数 data:储存开关信息的结构体
* @return 当全部开关都打开时返回true
*/
bool find_result(int n,int i,int j,my_data &data)
{
if (n == 0)
{
///判断是否开关是否都打开
return data.field[1] == 15
&& data.field[1] == data.field[2]
&& data.field[2] == data.field[3]
&& data.field[3] == data.field[4];
}
j++;
if (j > 4)
{
i += 1, j = 1;
}
if (i > 4)
{
return false;
}
for (; i <= 4; i++)
{
for (; j <= 4; j++)
{
flip(i, j, data);
data.op[i][j] = true;
if (find_result(n - 1, i, j,data))
{
return true;
}
data.op[i][j] = false;
flip(i, j, data);
}
j = 1;
}
return false;
}
void get_result(my_data &data)
{
for (size_t i = 0; i <= 16; i++)
{
if (find_result(i,1,0,data))
{
cout << i << endl;
///遍历输出所有操作
for (size_t i2 = 1; i2 <= 4; i2++)
{
for (size_t i3 = 0; i3 <=4; i3++)
{
if (data.op[i2][i3])
{
cout << i2 << " " << i3 << endl;
}
}
}
return;
}
}
cout << "Impossible" << endl;
}
int main()
{
struct my_data data_temp;
memset(data_temp.field, 0, sizeof(data_temp.field));
memset(data_temp.op, false, sizeof(data_temp.op));
read(data_temp.field);
get_result(data_temp);
system("pause");
return 0;
}