poj 2965

来源:互联网 发布:fc2视频域名更改 编辑:程序博客网 时间:2024/05/22 16:01
     这道题可以用搜索做,不过有一种更为简单巧妙的方法,在网上看了大神的介绍才知道的。
     1,有一点容易明白,一个位置改变了偶数次的话,状态是不变的,改变了奇数次的话,状态才和原来的相反。
     2,现在考虑如何把一个位置的‘+’变成‘-’ ,而让其它位置不变?可以先以该位置做一次题目中的翻转,再让该行和该列的每一个元素做一次题目中的翻转,可以发现,'+'号的位置做了9次改变,而该行该列的其它元素改变6次,剩下的元素改变了2次。
     根据以上两点,在程序中每遇到一个‘+’,就让‘+’所在行列的每个元素自增1,表示翻转了一次。最后将矩阵中每个元素模2,若为1,说明该位置需要翻转一次(为什么不是多次 呢?因为翻转3次的效果和翻转1次的效果是相同的),若为0,则跳过,不需要翻转。

  代码如下:

#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<cmath>#include<algorithm>#include<queue>#include<stack>#include<set>#include<map>using namespace std;typedef long long ll;const int M=1010;const int N=50010;const int INF=1e9;const double PI=acos(-1.0);const double Exp=exp(1.0);int n,m,ans;bool s[M][M];char g[M][M];void slove(){    int i,j;    memset(s,false,sizeof(s));    for (i=0;i<4;i++){        for (j=0;j<4;j++) {            if (g[i][j]=='+'){                s[i][j]=!s[i][j];                for (int k=0;k<4;k++){                    s[i][k]=!s[i][k];                    s[k][j]=!s[k][j];                }            }        }    }    for (i=0;i<4;i++)        for (j=0;j<4;j++) if (s[i][j]) ans++;    cout<<ans<<endl;    for (i=0;i<4;i++)        for (j=0;j<4;j++) if (s[i][j]) cout<<i+1<<" "<<j+1<<endl;}int main(){    while(~scanf("%s",g[0]))    {        ans=0;        for (int i=1;i<4;i++) scanf("%s",g[i]);        slove();    }}


0 0
原创粉丝点击