2017年3月25日 | ljfcnyali
题目大意
一个冰箱上有4*4共16个开关,改变任意一个开关的状态(即开变成关,关变成开)时,此开关的同一行、同一列所有的开关都会自动改变状态。要想打开冰箱,要所有开关全部打开才行。
Sample Input
-+--
----
----
-+--
Sample Output
6
1 1
1 3
1 4
4 1
4 3
4 4
1
2
3
4
5
6
7
6
1 1
1 3
1 4
4 1
4 3
4 4
题目分析
可以显然的发现,要想将一个点翻转,就需要一种策略:
把开关本身以及其同一行同一列的开关(总共7个)都进行一次操作,结果是,开关本身状态改变了7次,开关同一行、同一列的开关状态改变了4次,其他开关状态改变了2次。如
所以说,我们只需要将重复的操作删去,就可以水过这道题目。
AC代码
/*************************************************************************
> File Name: POJ2965.cpp
> Author: ljf-cnyali
> Mail: ljfcnyali@gmail.com
> Created Time: 2017/3/25 13:45:26
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
using namespace std;
#define REP(i, a, b) for(int i = (a), _end_ = (b);i <= _end_; ++ i)
#define mem(a) memset((a), 0, sizeof(a))
#define str(a) strlen(a)
int n, m;
int Map[5][5], v[5][5];
void flip(int x, int y) {
++ v[x][y];
REP(i, 1, 4)
Map[x][i] = 1 - Map[x][i];
REP(i, 1, 4)
if(i != x)
Map[i][y] = 1 - Map[i][y];
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
REP(i, 1, 4) {
REP(j, 1, 4) {
scanf("%c", &Map[i][j]);
if(Map[i][j] == '+')
Map[i][j] = 1;
else
Map[i][j] = 0;
}
getchar();
}
REP(i, 1, 4)
REP(j, 1, 4)
if(Map[i][j]) {
REP(t, 1, 4)
flip(i, t);
REP(t, 1, 4)
if(t != i)
flip(t, j);
}
int ans = 0;
REP(i, 1, 4)
REP(j, 1, 4)
if(v[i][j] % 2 != 0)
++ ans;
printf("%d\n", ans);
REP(i, 1, 4)
REP(j, 1, 4)
if(v[i][j] % 2 != 0)
printf("%d %d\n", i, j);
return 0;
}