Lamps 题解

Lamps

【题目描述】
有一个\(n \times m\)的灯具,每个格子里都有一盏小灯。每一列格子的下方都有一个开关,可以控制整列格子的灯的状态变化。就是说按一下这个开关,那么这列上的灯的状态都会改变。如果某一行的所有灯的状态都是开着的,那么这一行就称为是「Light」的。
给你这个灯具的初始状态,你需要精确地按次开关。求最多有几行是「Light」的。
【输入格式】
第一行三个正整数\(N,M\)\(K\),满足\(1 \leq n,m \leq 100\),\(0 \leq k \leq 1000\)
接下来\(N\)行,每行一个长度为\(M\)\(01\)字符串,\(1\)表示这盏灯是开着的,\(0\)表示这盏灯是关着的。
【输出格式】
输出仅包含一个整数,为最多的的行数。
【样例输入】
3 2 1
01
10
10
【样例输出】
2

蒟蒻的第四篇题解。

萌新拿到了这道题想到了暴力搜索,但是很明显不能过会超时QAQ。
后来经过分析,发现没有必要对于同一列操作两次以上,这样会回到原先的情况(除非是消磨步数),所以使用枚举法(暴力???)。
枚举每一种可能性,让被枚举的那行成为「Light」。
发现一行成为「Light」之后这种情况就被固定了下来,多余的次数用来消磨掉,如果多余次数正好是奇数,只能遗憾say byebye了。
显然步数不够的时候也只能再见。
处理使一行「Light」时,要是另一行与这行一模一样,这行一定也会成为「Light」行,那么可能最大方案数 +1。
最后把方案数进行比较输出最大值就行了。

#include<iostream>
#include<cstdio>
#include<string>//头文件
using namespace std;
char a[101][101];//储存开关情况
int sum[101];//记录每行需要打开的次数
int main()
{
	std::ios::sync_with_stdio(false);//关闭同步,加速
	int i,j,k;
	int _i,_j,_k;
	int flag,ans,maxn=-1;//-1角逐出最大值
	int T,t,n,m;
	
	cin>>n>>m>>k;
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			cin>>a[i][j];
			if(a[i][j]=='0')
			{
				sum[i]++;//记录每行操作数
			}
		}
	}
	for(i=1;i<=n;i++)
	{
		_k=k-sum[i];//用_k记录剩余步数
		if(_k<0)continue;//步数不够
		if(_k&1)continue;//剩余奇数次,位运算加速,相当于if(k%2==1)
		ans=1;//初始化
		for(_i=1;_i<=n;_i++)
		{
			if(_i==i)continue;//防止自己和自己比较
			flag=1;
			for(_j=1;_j<=m;_j++)
			{
				if(a[_i][_j]!=a[i][_j])
				{
					flag=0;
					break;
				}
			}
			if(flag==1)ans++;//如果一模一样,可能次数增加
		}
		maxn=max(maxn,ans);//比较最大值
	}
	cout<<maxn;
	
	return 0;
}
posted @ 2020-11-03 23:33  蒟酱  阅读(129)  评论(0)    收藏  举报