【BZOJ2484】[SDOI2011]打地鼠(暴力)

【BZOJ2484】[SDOI2011]打地鼠(暴力)

题面

BZOJ
洛谷

题解

看到数据范围这题就应该是一个暴力题了。
先考虑假如我们知道了锤子的大小\(R*C\),那么显然只需要从左上角开始从左往右从上往下一个个砸就行了,因为你砸到当前位置之后左上角一定没有限制了,只有当前这个位置还有限制。所以直接暴力就是\(O(n^6)\)的了。似乎可以\(BIT\)之类的优化一下,差不多可以做到\(O(n^4log^2n)\)
然后不够优秀,我们想想,枚举\(R*C\)之后限制是考虑左上角是否都变成了\(0\)
如果我们\(R*1\)可以把东西砸完,即一行行的砸是能够符合条件的,并且\(1*C\)也能够砸完,即一列列也是满足条件的,那么\(R*C\)显然也是合法的,等价于我们把\(C\)列每次一起砸就好了。
那么分开枚举\(R\)\(C\)\(\mbox{check}\)就行了,这样子暴力的复杂度是\(O(n^4)\)就可以过了。也就是\(O(n)\)枚举,\(O(n^2)\)考虑所有位置,\(O(n)\)删掉当前位置对于后面的限制。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 105
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int n,m,a[MAX][MAX],s[MAX][MAX];
int R,C,sum;
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			sum+=(a[i][j]=read());
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j)
			for(int k=1;k<=m;++k)
				s[j][k]=a[j][k];
		for(int j=1;j<=m;++j)
			for(int k=1;k+i-1<=n;++k)
				for(int l=k+i-1;l>=k;--l)
					s[l][j]-=s[k][j];
		bool fl=true;
		for(int j=1;j<=m;++j)
			for(int k=1;k<=n;++k)
				if(s[k][j])fl=false;
		if(fl)R=i;
	}
	for(int i=1;i<=m;++i)
	{
		for(int j=1;j<=n;++j)
			for(int k=1;k<=m;++k)
				s[j][k]=a[j][k];
		for(int j=1;j<=n;++j)
			for(int k=1;k+i-1<=m;++k)
				for(int l=k+i-1;l>=k;--l)
					s[j][l]-=s[j][k];
		bool fl=true;
		for(int j=1;j<=n;++j)
			for(int k=1;k<=m;++k)
				if(s[j][k])fl=false;
		if(fl)C=i;
	}
	printf("%d\n",sum/(R*C));
	return 0;
}
posted @ 2018-10-31 22:39  小蒟蒻yyb  阅读(216)  评论(0编辑  收藏  举报