BZOJ2241 SDOI2011 打地鼠 枚举
题意:给定一个N*M数字矩阵,求一个全1矩阵,使得该矩阵在经过复制后,在满足每次放置的位置不存在0的情况下,放置的矩阵数最少,求最少次数。
题解:由于数据很小所以可以暴力枚举所求矩阵的长和宽然后检验。由于所求矩阵的大小一定是所有数和的因数,然后矩阵越大放的次数就越少,所以倒序枚举。
#include <cstdio> #include <climits> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAXN=100+2; int a[MAXN][MAXN],b[MAXN][MAXN],N,M,S,Ans=INT_MAX; bool Check(int x,int y){ memcpy(b,a,sizeof(b)); for(int i=1;i<=N;i++) for(int j=1,t;j<=M;j++){ t=b[i][j]; if(t && i+x-1<=N && j+y-1<=M) for(int l=i;l<=i+x-1;l++) for(int r=j;r<=j+y-1;r++){ b[l][r]-=t; if(b[l][r]<0) return 0; } if(b[i][j]) return 0; } return 1; } int main(){ scanf("%d %d",&N,&M); for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) scanf("%d",a[i]+j),S+=a[i][j]; for(int i=N;i;i--) for(int j=M;j;j--) if(S%(i*j)==0 && S/(i*j)<Ans && Check(i,j)) Ans=S/(i*j); cout << Ans << endl; return 0; }