2017-10-02
原题链接
题目大意:有4*4个开关,以‘+’表示开关的关状态,‘-’表示开关的开状态。现在可以通过给出一对值[i,j]来同时改变第i行和第j列所有开关的状态。求使得所有开关状态变为开所需的最少值对数,并给出这些值对。
样例输入:
-+--
----
----
-+--
样例输出:
6
1 1
1 3
1 4
4 1
4 3
4 4
本题的思想和POJ1753这题非常接近,也是枚举+DFS。需要注意的是,在同时改变第i行和第j列全部开关的状态时,第i行第j列的那个开关状态被改变了两次。
代码:
#include <iostream>
using namespace std;
bool swts[6][6]; //所有开关
int chans = 1; //改变开关状态次数
bool isSolved = false; //是否有解
int ans[18][2]; //记录解
void isAnswer() { //是否所有开关已经打开,是则为true
for(int i = 1; i < 5; i++)
for(int j = 1; j < 5; j++)
if(swts[i][j] != true) return;
isSolved = true;
return;
}
void switchSwts(int x,int y) {//把x行y列的开关状态改变
for(int i = 1; i < 5; i++) {
swts[x][i] = !swts[x][i];
swts[i][y] = !swts[i][y];
}
swts[x][y] = !swts[x][y]; //*在上个代码段中,该开关状态被改变了两次*
}
void dfs(int x,int y,int dep) {
isAnswer();
if(dep == chans) return;
if(isSolved || x > 4) return;
ans[dep][0] = x;
ans[dep][1] = y;
switchSwts(x,y); //改变开关状态
if(y < 4) dfs(x,y+1,dep+1);
else dfs(x+1,1,dep+1);
ans[dep][0] = x;
ans[dep][1] = y;
switchSwts(x,y); //还原
if(y < 4) dfs(x,y+1,dep);
else dfs(x+1,1,dep);
}
int main()
{
char c; //初始时开关的状态,-为true,+为false
for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++) {
cin >> c;
swts[i+1][j+1] = (c == '-' ? true : false);
}
for(chans = 1; chans <= 16; chans++) {//枚举1~16步
dfs(1,1,0);
if(isSolved) break;
}
cout << chans << endl;
for(int i = 0; i < chans; i++)
cout << ans[i][0] << " " << ans[i][1] << endl;
return 0;
}