翻硬币(搜索)
来源:互联网 发布:sql注入绕过 concat 0x 编辑:程序博客网 时间:2024/05/22 12:59
题目大意
有一个n*m的格子,每个格子上有一个硬币,用0表示正面朝上,1表示反面朝上。
一次操作你可以将一行或一列的硬币都反转,问你是否能够进行一系列的操作之后使得所有的硬币都朝上。
分析
这道题和黑白棋那道类似,黑白棋那道有个启发式信息是一个点不会反转超过一次,这道题也是同样的道理,一行或一列不会反转超过一次。
然后我们观察一种可能的反转情况:
我们可以发现这样的信息:反转的情况类似于“井”状,并且出于交叉出的点一定是0,因为只有0点在反转两次后才会依然朝上。
继续观察我们发现了一条有用的信息:
一种可行的反转操作集合的补集也一定是可行的,如下图:
这样,我们不妨将第一行反转,对于第一行中为0的点我们将这些点所在的列也反转,做了这样一个初始操作之后我们继续看后面的行,后面不可能在进行列反转操作了,因为这会破坏第一行的状态,所以我们只需要去统计后面每一行是否都是相同的数就行了。
还有需要注意的一点就是题目中给的图范围是n*m<
代码
#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<cstdlib>#include<queue>#include<map>#include<algorithm>#include<set>#include<stack>using namespace std;const long long int INF=0x7fffffffffffffff;const int MAXN= 1000005;int a[MAXN];int T;int n,m;bool x_change[MAXN];//x_change[i]为1表示第i行反转,0表示不反转bool y_change[MAXN];void Init(){ memset(a,0,sizeof(a)); memset(x_change,0,sizeof(x_change)); memset(y_change,0,sizeof(y_change));}bool Work(){ x_change[1]=1; for(int j=1;j<=m;j++) { if(a[j]==0)y_change[j]=1; } int cnt;// for(int i=1;i<=n;i++)//n行m列 { cnt=0;//表示第i行有多少0 for(int j=1;j<=m;j++) { int loc=(i-1)*m+j; if(a[loc]==0 && y_change[j]==0)cnt++; if(a[loc]==1 && y_change[j]==1)cnt++; } if(cnt>0 && cnt<m)return 0; } return 1;}int main(){ scanf("%d",&T); while(T--) { Init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&a[(i-1)*m+j]); } } if(Work()==1)printf("YES\n"); else printf("NO\n"); } return 0;}
0 0
- 翻硬币(搜索)
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- 翻硬币
- Spring的AOP介绍
- js--数据结构--链表
- HBase Java简单示例
- Annotation方式实现AOP
- AOP的Advice
- 翻硬币(搜索)
- XML方式实现Spring的AOP
- Spring简单与数据库连接
- Spring整合Hibernate:1、annotation方式管理SessionFactory
- Spring整合Hibernate:2、使用Annotation方式进行声明式的事务管理
- Spring整合hibernate:3、使用XML进行声明式的事务管理
- @Transactional的readOnly、timeout
- Java发送短信
- 使用为知笔记客户端发布博客到【博客园】