//在poj1753 基础上改造一下, ac用时大概 300~500 ms 不会超时
//思路非常简单,先dfs求出最小次数,再次dfs记录下 达到最小次数的 路径即可
#include<iostream>
using namespace std;#include<cstdio>
#include<cstring>
bool arr[4][4]={false}; // + closed用0表示关 - open用1表示开
int ans = 999999; //其实只要初始化为17 就行,最多转16次 ,
bool flag;
int a[20],b[20]; // 两个数组用来记录下标,当然你也可以有struct pos{ int x,int y} array[20];
void flip(int x,int y)
{
int i,j;
for(i=0;i<4;i++)
{
arr[i][y] = !arr[i][y]; // 翻所在列
}
for(j=0;j<4;j++)
{
if(j!=y)
{
arr[x][j] = !arr[x][j]; // 翻所在行
}
}
}
bool judge() //判断是否全开,即全部为 - 即是否为true
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(arr[i][j] != true)
return false;
return true;
}
void dfs(int x,int y,int deep){ //dfs深度搜索
if(judge()){
if(deep < ans)
ans = deep; //ans 保存最小翻转次
return ;
}
if(x<0 || x>3 || y<0 || y>3)
return ;
int nx,ny;
nx=(x+1)%4;
ny=y+(x+1)/4;
flip(x,y);
dfs(nx,ny,deep+1);
flip(x,y);
dfs(nx,ny,deep);
}
void Dfs(int x,int y,int deep){ //dfs深度搜索
if(judge()){
if(deep == ans)
flag=true; //已达到最小翻转次数
return ;
}
if(flag || x<0 || x>3 || y<0 || y>3) //多了一个条件满足flag即可退出
return ;
int nx,ny;
nx=(x+1)%4; // 注意此处按列搜索,也可稍加改造按列搜索 结果可能与答案不一样,只要找出一条翻转路径即可
ny=y+(x+1)/4;
/*
y = (y+1)%4; //相当于按行遍历 这种写法 测试样例与答案一样
nx = x + (y+1)/4;
*/
flip(x,y);
Dfs(nx,ny,deep+1);
a[deep]=x; //记录下标x
b[deep]=y; //记录下标y
flip(x,y);
Dfs(nx,ny,deep);
}
int main(){
char str[5];
int i,j;
for(i=0;i<4;i++)
{
cin >> str;
for(j=0;j<4;j++)
if(str[j] == '-')
arr[i][j] = true;
}
dfs(0,0,0); // 先计算出 最小翻转次数
flag=false;
Dfs(0,0,0); //再次Dfs 稍作修该 保存路径 , 当 达到 dfs求出最小次数ans 即可将flag 表为true
cout << ans << endl;
for(i=0;i<ans;i++){
cout << a[i]+1 <<" " << b[i]+1 << endl;
//注意 he state of a handle in any location [i, j] (1 ≤ i, j ≤ 4)
//行列都是从1开始 ,我开的数组是 从(0,0) ~ (3,3)
}
return 0;
}