题意:给定你一个N*M大小的矩阵,然后每次更新使得一个大小为a * b的子矩阵内的所有元素的值减一,问最后能否通过有限次操作使得原矩阵的元素都变为0
思路:给定大小的矩阵的加减操作,可以想到二维差分,之后就是遍历矩阵中的每个点,然后当前的点的值加上差分数组的值,假如相加之后的值等于0就证明正好这个点被更新为0去看下一个位置,如果小于0的话,就证明前面的点的更新过程使得这个点的值已经变成了负数不满足题意,如果大于0的话,就证明想要把这个点更新成为0的话,还要再通过那个子矩阵更新一下。
最后所有点更新完成之后,看一下有没有值仍然大于零的点,有的话就不符合题意,否则就是可行的。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 7;
int mp[MAXN][MAXN];
int d[MAXN][MAXN];
int main()
{
int n,m,t,a,b;
scanf("%d",&t);
while(t--){
memset(d,0,sizeof(d));
//memset(mp,0,sizeof(mp));
scanf("%d%d%d%d",&n,&m,&a,&b);
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
scanf("%d",&mp[i][j]);
//cin>>mp[i][j];
}
}
int flag = 0;
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++){
d[i][j] += d[i][j-1] + d[i-1][j] - d[i-1][j-1];
int x = mp[i][j] + d[i][j];
if(x == 0) continue;
else if(x < 0){//某个点背前面的更新加出负的了
//flag = 1;
break;
}
else if(x > 0 && i + a - 1 <= n && j + b - 1 <= m){
d[i][j] -= x;
d[i][j+b] += x;
d[i+a][j] += x;
d[i+a][j+b] -= x;
}
}
}
for(int i = 1;i <= n;i ++){
for(int j = 1;j <= m;j ++)
if(mp[i][j] + d[i][j]){
puts("QAQ");
flag = 1;
break;
}
if(flag) break;
}
if(!flag) puts("^_^");
}
return 0;
}
借此复习一下二维差分的意义和实现,太笨比了。