POJ 2965 The Pilots Brothers’ refrigerator
[★★☆☆☆]枚举
题目大意:
一个冰箱上有4*4共16个开关,改变任意一个开关的状态(即开变成关,关变成开)时,此开关的同一行、同一列所有的开关都会自动改变状态。要想打开冰箱,要所有开关全部打开才行。
输入格式:
4*4矩阵
+表示关闭,-表示打开输出格式:
使冰箱打开所需要执行的最少操作次数,以及所操作的开关坐标。
解题思路:
水题,但是第一次提交居然超时了。。
后来一想,题目说的是求最小的次数,其实只要成功,操作次数是一样的。稍微想下就能证明出来。
另外一提,本题有更加省时的巧妙的做法,可以适用于更大的数据范围,具体方法去上网查咯~代码
#include <iostream>
#include <stack>
using namespace std;
const int INF = 1e9 +7;
struct ZB {
int x;
int y;
};
char map[5][5];
stack<ZB> as;
stack<ZB> s;
stack<ZB> ts;
int ans;
void f(int x, int y) {
if (map[x][y] == '+') map[x][y] = '-';
else map[x][y] = '+';
}
void fz(int x, int y) {
for (int i = 1; i <= 4; i++) {
f(x,i); f(i,y);
}
f(x,y);
}
bool allopen() {
int ap = 1;
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
if (map[i][j] == '+') ap = 0;
}
}
return ap;
}
bool dfs(int na, int res) {
if (res == 17) {
if (allopen() && na < ans){
ans = na;
while (!as.empty()) as.pop();
while (!s.empty()) {
ZB t;
t = s.top();
as.push(t); ts.push(t);
s.pop();
}
while (!ts.empty()) {
s.push(ts.top());
ts.pop();
}
return 1;
}
return 0;
}
int x, y;
x = (res)/4 + 1;
y = (res)%4;
if (y == 0){
x--; y = 4;
}
if(dfs(na,res+1)) return 1;
ZB tt = {x,y};
fz(x, y); na++; s.push(tt);
if (dfs(na, res+1)) return 1;
fz(x, y); na--; s.pop();
return 0;
}
int main() {
ans = INF;
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
scanf("%c",&map[i][j]);
}
getchar();
}
dfs(0, 1);
printf("%d\n", ans);
while (!as.empty()) {
ZB t;
t = as.top();
cout << t.x << ' ' << t.y << endl;
as.pop();
}
return 0;
}