文章中的名词理解;
1.翻转:+到-或-到+
2。操作:即为对其行和列的点翻转
1.首先得明白,对一个点只能进行奇次操作,即操作一次。取反原理
2.证明:要使一个为'+'的符号变为'-',必须其相应的行和列的操作数为奇数;可以证明,如果'+'位置对应的行和列上每一个位置都进行一次操作,则整个图只有这一'+'位置的符号改变,其余都不会改变.
思路如下:红色点将为接下来进行的操作点
假如为 : - - + -
- - - -
- - - -
- - - -
若对第一行的每一个点都进行操作,第一行每一个点都翻转4次,等价于没反转。
但是2,3,4行都翻转了一次,故变为+;有
- - + -
+ + + +
+ + + +
+ + + +
则剩2,3,4的红色点还没操作,操作后:
2,3,4行的每一个点(除红色点)都翻转一次;有
- - + -
- - + -
- - + -
- - + -
3列的每一个点都翻转3次;有
- - - -
- - - -
- - - -
- - - -
故证明
设置一个4*4的整型数组,初值为零,用于记录每个点的操作数,那么在每个'+'上的行和列的的位置都加1,得到结果模2(因为一个点进行偶数次操作的效果和没进行操作一样,这就是楼上说的取反的原理),然后计算整型数组中为1的个数并记录其位置。
代码如下:0ms
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char a[5][5]; int b[5][5]; int c[60]; int main() { int i,j,p,q; memset(b,0,sizeof(b)); for(i=0;i<4;i++) { for(j=0;j<4;j++) { cin>>a[i][j]; if(a[i][j]=='+') { for(p=0;p<4;p++) b[i][p]++; for(q=0;q<4;q++) b[q][j]++; b[i][j]--; } } } int k=0; int start=0; for(i=0;i<4;i++) { for(j=0;j<4;j++) { int l=b[i][j]; l%=2; if(l==1) { k++; c[start++]=i; c[start++]=j; } } } cout<<k<<endl; for(i=0;i<start;i+=2) { cout<<c[i]+1<<' '<<c[i+1]+1<<endl; } return 0; }