[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 }

 

posted @ 2021-11-20 18:04  yfmd  阅读(60)  评论(0编辑  收藏  举报