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

来源:互联网 发布:java入门视频百度网盘 编辑:程序博客网 时间:2024/04/30 15:02

题目大意:给出一个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;}


0 0