Enlace de tema
https://ac.nowcoder.com/acm/contest/7501?&headNav=www#question
Título
Dada una matriz de n * m, puede restar uno de todos los elementos de la matriz pequeña de a * b en la matriz varias veces y preguntar si se puede reducir a 0.
Ideas
Recorra cada elemento de arriba a abajo y de izquierda a derecha. Para el valor actual ai de cada elemento, todas las matrices a * b de la primera fila y la primera columna se restarán de ai. Una vez completado el recorrido, si todos los valores son Cero significa que se puede lograr; de lo contrario, no.
La complejidad del algoritmo de fuerza bruta es O (nmab), podemos usar el intervalo de optimización de diferencia bidimensional para modificar.
Diferencia unidimensional diff [i] = a [i] -a [i-1], agregue z al intervalo x, y, puede diff [x] + = z, diff [y + 1] - = z. Finalmente La suma del prefijo es la matriz original.
Diferencia bidimensional diff [i] [j] = a [i] [j] -a [i-1] [j] -a [i] [j-1] + a [i-1] [j-1] , Si se suma z al rectángulo x1 y1, x2 y2, entonces diff [x1] [y1] + = z, diff [x1] [y2 + 1] - = z, diff [x2 + 1] [y1] - = z, diff [x2 + 1] [y2 + 1] + = z. La matriz original puede usar un prefijo bidimensional y restaurar.
Reducimos los elementos de la matriz a 0, y la matriz de diferencias son todos ceros. Luego, atravesamos la matriz de diferencias. Si el elemento actual es mayor o igual que 0, el rectángulo pequeño con este punto como la primera fila y la primera columna se usa para la resta de intervalo usando la matriz de diferencias De lo contrario, se determina que la respuesta no existe.
Código
#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
//#define double long double
using namespace std;
typedef long long ll;
const int maxn=4005;
const int inf=0x3f3f3f3f;
int n,m,a,b;
int aa[maxn][maxn];
int diff[maxn][maxn];
int main(){
IOS
int tn;
cin>>tn;
while(tn--){
cin>>n>>m>>a>>b;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>aa[i][j];
diff[i][j]=aa[i][j]-aa[i-1][j]-aa[i][j-1]+aa[i-1][j-1];
}
bool bl=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int tmp=diff[i][j];
if(!tmp)
continue;
else if(tmp<0){
bl=0;
break;
}
else if(i<=n-a+1&&j<=m-b+1){
diff[i][j] -= tmp;
diff[i][j+b] +=tmp;
diff[i+a][j] +=tmp;
diff[i+a][j+b] -= tmp;
}
else{
bl=0;
break;
}
}
}
if(!bl)
cout<<"QAQ"<<endl;
else
cout<<"^_^"<<endl;
}
}