POJ2965 The Pilots Brothers' refrigerator(枚举+思维题)

题目大意:给出一个4×4的矩形,矩形上的“ + ”表示关闭状态,“ - ”表示打开状态,可以改变任意一点(i,j)的状态,改变该点状态的同时,第i行和第j列上的元素的状态也随之改变,问你事所有点都变成打开状态所需的最少翻转次数,同时输出要改变状态的点的坐标(坐标从1开始)。

分析:这题和POJ1753有点相似,但比1753更有思维性。首先我们先来看一下,对于矩形中的某点(i,j),如果我们改变这一点状态的同时,随便改变其所在行和列上剩下的6个点的状态,那么会发生什么情况呢?答案就是:除了(i,j)这一点的状态改变之外,其他6个点的状态都不变。这很好理解,对于(i,j)点来说,一共改变了7次状态,奇数次改变等同于一次,而其所在的i行j列上剩下的6个元素呢,每个元素分别改变了4次状态,偶数次改变等于是没有变化的。这就意味着,我们只要枚举矩形中的每一点,遇到“ + ”,后,改变其所在的行和列上所有的元素的状态即可。这样一轮枚举下来,所有的点就都变成了打开状态。至于改变状态的点的坐标呢,我们可以在改变“ + ”点的状态的同时,用另外一个数组标记即可,然后输出这些被标记的点。

实现代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
bool s[4][4];
char map[4][4];
int main()
{
    int ans1[20],ans2[20];
    memset(s,0,sizeof(s));
    for(int i=0;i<4;i++)
      scanf("%s",map[i]);
    for(int i=0;i<4;i++)
      for(int j=0;j<4;j++)
        if(map[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];
            }
        }
    int t=0;
    for(int i=0;i<4;i++)
      for(int j=0;j<4;j++)
        if(s[i][j])
        {
            ans1[t]=i+1;
            ans2[t++]=j+1;
        }
    printf("%d\n",t);
    for(int i=0;i<t;i++)
      printf("%d %d\n",ans1[i],ans2[i]);
    return 0;
}


你可能感兴趣的:(POJ2965 The Pilots Brothers' refrigerator(枚举+思维题))