[Bzoj2241] to fight rats

First consider how to determine a r * c matrix eligibility, easy to find the upper left corner of the matrix and can not be hit anything else, requires the upper left corner of the matrix r * c can not exceed the top left corner of the element, after empathy constantly medals for the most & leftmost non-zero points can be used to optimize the differential, complexity is $ o (n ^ {4} ) $ (n and m are the same order)
(plus some divisible then, descending to enumeration pruning can live a)
positive solutions is such that the maximum enumeration 1 * c matrix, enumeration of the largest matrix r * 1, r * c matrix is the answer (the difference with maintenance)
in order to prove the correctness of this, divided consider two parts:
1. the necessity that r * c matrix can launch legal matrix 1 * c and r * 1 legitimate, apparently set up (with a matrix of c times r * 1 / r times c * matrix to 1 )
2. sufficiency, namely the matrix 1 * c and r * 1 can launch legal r * c matrix legitimate, considering the current top-left corner, knocked on end x number of times, indicating that each column in excess of x, then the inevitable each row can cause knock at least x, i.e. a matrix of r * c x times knock
problem to obtain certificates, then the complexity of the final solution was positive $ o (n ^ {3} ) $ (n and m are the same order )

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,s,ans,a[105][105],b[105][105];
 4 bool pd(int r,int c){
 5     memcpy(b,a,sizeof(a));
 6     for(int i=1;i<=n;i++)
 7         for(int j=1;j<=m;j++)
 8             if (b[i][j]){
 9                 if ((i+r-1>n)||(j+c-1>m))return 0;
10                 int p=b[i][j];
11                 for(int x=i;x<i+r;x++)
12                     for(int y=j;y<j+c;y++)
13                         if ((b[x][y]-=p)<0)return 0;
14             }
15     return 1;
16 }
17 int main(){
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;i++)
20         for(int j=1;j<=m;j++){
21             scanf("%d",&a[i][j]);
22             s+=a[i][j];
23         }
24     for(int i=n;i;i--)
25         for(int j=m;j;j--)
26             if ((s%(i*j)==0)&&(i*j>ans)&&(pd(i,j)))ans=i*j;
27     printf("%d",s/ans);
28 }
View Code

 

Guess you like

Origin www.cnblogs.com/PYWBKTDA/p/11842666.html