描述:
L用硬币玩游戏。他在n*m的矩阵中的每个小格中放一枚硬币,他想将所有的硬币都变成正面向上,但是,他给自己增加一些难度,他只能将整行或者整列的硬币都翻面。当然,他一点也不想做无用功,所以,他想知道当前的状态是否能通过一系列操作后使得所有硬币正面朝上。
输入:
首先是一个T,代表数据的组数;每组数据的第一行给出一个n和m,代表行数和列数;接下来n行,每行由m个数(0或者1),0表示硬币正面朝上,1表示硬币反面朝上;
数据范围:
n>=1
m>=1
n*m<=1e6
输出:
如果能使得所有硬币正面朝上,输出YES;
否则输出NO;
样例输入
2 2 3 1 1 1 0 0 0 2 2 1 1 0 1
样例输出
YES NO
比赛时想了好久也没有思路。赛后看题解,恍然大悟,记得之前做过一道相似的题。
思路:枚举第一行是否翻转,可知道哪些列翻转,然后根据第一列的情况即可推出所有行的情况。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> using namespace std; #define N 1000005 int coins[N],row[N],col[N]; int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&coins[i*m+j]); for(int i=0;i<m;i++) { if(coins[i]==1) col[i]=1; } for(int i=1;i<n;i++) { if(coins[i*m]==1&&col[0]==0) row[i]=1; else if(coins[i*m]==0&&col[0]==1) row[i]=1; } bool flag=1; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(row[i]==1&&col[j]==1&&coins[i*m+j]==1) { flag=0; break; } else if(row[i]==1&&col[j]==0&&coins[i*m+j]==0) { flag=0; break; } else if(row[i]==0&&col[j]==1&&coins[i*m+j]==0) { flag=0; break; } else if(row[i]==0&&col[j]==0&&coins[i*m+j]==1) { flag=0; break; } } if(flag) { printf("YES "); continue; } memset(row,0,sizeof(row)); memset(col,0,sizeof(col)); for(int i=0;i<m;i++) { if(coins[i]==0) col[i]=1; } for(int i=1;i<n;i++) { if(coins[i*m]==1&&col[0]==0) row[i]=1; else if(coins[i*m]==0&&col[0]==1) row[i]=1; } flag=1; for(int i=1;i<n;i++) for(int j=0;j<m;j++) { if(row[i]==1&&col[j]==1&&coins[i*m+j]==1) { flag=0; break; } else if(row[i]==1&&col[j]==0&&coins[i*m+j]==0) { flag=0; break; } else if(row[i]==0&&col[j]==1&&coins[i*m+j]==0) { flag=0; break; } else if(row[i]==0&&col[j]==0&&coins[i*m+j]==1) { flag=0; break; } } if(flag) printf("YES "); else printf("NO "); } return 0; }