[SDOI2011]打地鼠
1 #include<bits/stdc++.h> 2 using namespace std; 3 namespace _xzy 4 { 5 typedef long long ll; 6 inline int read() 7 { 8 ll sm=0,flag=1; 9 char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){sm=sm*10+ch-'0';ch=getchar();} 12 return sm*flag; 13 } 14 ll m,n,ans=1e9,sum; 15 ll g[102][102],copy[102][102]; 16 int pd(ll r,ll c) 17 { 18 //copy一遍,以免对之后的计算造成影响 19 for(ll i=1;i<=m;++i) 20 for(ll j=1;j<=n;++j) 21 copy[i][j]=g[i][j]; 22 for(ll i=1;i<=m;++i) 23 for(ll j=1;j<=n;++j) 24 { 25 if(copy[i][j]==0)continue;//如果现在没有地鼠,那么就不需要打了 26 ll x=copy[i][j];//用x记录挥舞次数 27 //因为是恰好打完地鼠,且每次挥舞都有一个左上边界,所以找到一个有地鼠的先全打死就是了 28 for(ll k=i;k<=i+r-1;++k) 29 for(ll g=j;g<=j+c-1;++g) 30 { 31 //因为每次挥舞锤子范围内的地鼠都要遭殃,因此都要减去x 32 copy[k][g]=copy[k][g]-x; 33 if(copy[k][g]<0)return 0;//如果地鼠数量小于零,这说明不合法 34 if(k>m)return 0;//超过了边界,非法 35 if(g>n)return 0; 36 } 37 } 38 for(ll i=1;i<=m;++i) 39 for(ll j=1;j<=n;++j) 40 if(copy[i][j]!=0)return 0; 41 //如果有的地鼠没打完,非法 42 return 1; 43 } 44 void My_main() 45 { 46 m=read();n=read(); 47 for(ll i=1;i<=m;++i) 48 for(ll j=1;j<=n;++j) 49 { 50 g[i][j]=read(); 51 sum+=g[i][j]; 52 } 53 //n和m太小了,这给枚举锤子的大小提供了可能 54 for(ll i=1;i<=m;++i) 55 for(ll j=1;j<=n;++j) 56 { 57 //题意:每次挥舞锤子时,恰好有r*c只地鼠被打掉 58 if((sum)%(i*j)!=0)continue;//要想恰好全打死,就要使地鼠总个数是锤子面积的倍数 59 if(pd(i,j)) 60 ans=min(ans,(sum)/(i*j));//挥舞次数为总数除以面积 61 } 62 cout<<ans; 63 } 64 } 65 int main() 66 { 67 _xzy::My_main(); 68 return 0; 69 }