题目:
“飞行员兄弟”这个游戏,需要玩家顺利的打开一个拥有 16个把手的冰箱。已知每个把手可以处于以下两种状态之一:打开或关闭。只有当所有把手都打开时,冰箱才会打开。把手可以表示为一个 4×4的矩阵,您可以改变任何一个位置 [i,j]上把手的状态。但是,这也会使得第 i行和第 j列上的所有把手的状态也随着改变。请你求出打开冰箱所需的切换把手的次数最小值是多少。
输入格式
输入一共包含四行,每行包含四个把手的初始状态。符号 +
表示把手处于闭合状态,而符号 -
表示把手处于打开状态。至少一个手柄的初始状态是关闭的。
输出格式
第一行输出一个整数 N,表示所需的最小切换把手次数。接下来 N行描述切换顺序,每行输出两个整数,代表被切换状态的把手的行号和列号,数字之间用空格隔开。
注意:如果存在多种打开冰箱的方式,则按照优先级整体从上到下,同行从左到右打开。
数据范围
1≤i,j≤4
输入样例:
-+--
----
----
-+--
输出样例:
6
1 1
1 3
1 4
4 1
4 3
4 4
分析:这题与n-皇后的问题有相似的地方,我的想法是遍历所有的点的所有状态(改变这个点的状态和不改变这个点的状态),直到整个数组符合要求为止。具体的操作用vector<pair<int,int>>来存储。因为没个点都有2种情况,一共有4*4个点,所以时间复杂度为O(),详细见代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef pair<int, int> PII;
//冰箱的初始把手状态
int map[10][10];
//我们希望的最终的冰箱状态,是为了检验冰箱的把手是否全部打开而存在
int moduel[10][10];
//op表示操作数最短的一组方法,tmp表示当前的这组操作方法
vector<PII> op, tmp;
//改变x行y列的把手状态
void change(int x, int y) {
for (int i = 1; i <= 4; i++) {
map[i][y] = 1 - map[i][y];
}
for (int j = 1; j <= 4; j++) {
map[x][j] = 1 - map[x][j];
}
map[x][y] = 1 - map[x][y];
}
//检验冰箱把手是否全部打开
bool cmp(int a[10][10], int b[10][10]) {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
if (a[i][j] != b[i][j])return false;
}
}
return true;
}
void dfs(int x, int y){
//如果我们将4*4个把手全部遍历完了,就检验是否符合要求
if(x == 4 && y == 5){
if(cmp(map, moduel)){
if(op.empty() || tmp.size() < op.size())
op = tmp;
}
return;
}
//边界问题
if(y == 5)x ++, y = 1;
//改变状态
change(x, y);
tmp.push_back({x, y});
dfs(x , y + 1);//**
//还原状态
change(x , y);
tmp.pop_back();
//不改变状态
dfs(x, y + 1);
}
int main(){
for(int i = 1; i <= 4; i ++){
for(int j = 1; j <= 4; j++){
char a;
cin >> a;
if(a == '+')map[i][j] = 1;
else map[i][j] = 0;
}
}
//从(1,1)这个点开始遍历
dfs(1, 1);
int size = op.size();
cout << size << endl;
for(int i = 0; i < size; i ++) cout << op[i].first << " " << op[i].second << endl;
return 0;
}
扩展:DFS的步骤
在DFS的过程中,我们先依次从(1,1)开始遍历到(4,4),之后就会dfs(4,5),这个时候进入if(x == 4 && y == 5){....}如果数组没有达到我们的要求,就会return到(4,4)这个点中的**行(在代码中注释了),然后还原状态,走不将其改变状态的这个分支。也就是说,DFS就是不断的试探回溯,如果走的这个分支不行,就回溯回去,将状态还原,再走另外一个分支。如果大家有时间可以去看看n-皇后问题,与这个比较相似.