1.链接地址
https://vjudge.net/problem/POJ-2965#author=nooko
2.问题描述
大体题意:一个冰箱上有4*4共16个开关,改变任意一个开关的状态(即开变成关,关变成开)时,此开关的同一行、同一列所有的开关都会自动改变状态。要想打开冰箱,要所有开关全部打开才行。 输入:一个4×4的矩阵,+表示关闭,-表示打开; 输出:使冰箱打开所需要执行的最少操作次数,以及所操作的开关坐标。
输入样例
-+-- ---- ---- -+--
输出样例
6 1 1 1 3 1 4 4 1 4 3 4 4
3.解题思路
同样采用递归枚举的方法,记录步数可用两个数组,一个用来记录临时步数,一个用来记录最终步数,当此时的步数比已经记录的还少时则更新最终步数,要理解函数堆栈和递归枚举的概念
4.算法实现源代码
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int map[5][5]; int x[20]; int y[20]; int ansX[20]; int ansY[20]; int ans = 33; void build() { char c; memset(map, 0, sizeof(map)); for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) { cin>>c; if(c == '-') map[i][j] = 1; else map[i][j] = 0; } } } void flip(int s) { int x1 = s/4; int y1 = s%4; for(int i = 0; i < 4; i++) { map[i][y1] = !map[i][y1]; map[x1][i] = !map[x1][i]; } map[x1][y1] = !map[x1][y1]; } bool complete() { for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) if(map[i][j] == 0) return false; } return true; } void dfs(int s, int b) { if(complete()) { if(ans > b) { ans = b; for(int i = 1; i <= ans; i++) { ansX[i] = x[i]; ansY[i] = y[i]; } } return; } if(s >= 16) return; dfs(s+1, b); flip(s); x[b+1] = s/4+1; y[b+1] = s%4+1; dfs(s+1, b+1); flip(s); } int main() { build(); dfs(0, 0); printf("%d\n", ans); for(int i = 1; i <= ans; i++) { printf("%d %d\n", ansX[i], ansY[i]); } return 0; }