$\rm Sol.$
首先可以发现
同时可以发现
设 $c_i$ 和 $d_i$ 分别表示每行
$$\begin{bmatrix}
+1 & -1 & +1 & -1 \\
+1 & -1 & +1 & -1 \\
+1 & -1 & +1 & -1 \\
+1 & -1 & +1 & -1 \\
\end{bmatrix}
\rm and
\begin{bmatrix}
+1 & +1 & +1 & +1 \\
-1 & -1 & -1 & -1 \\
+1 & +1 & +1 & +1 \\
-1 & -1 & -1 & -1 \\
\end{bmatrix}
$$
列出需要满足的方程
$$ 0 \leqslant a_{i, j} \pm c_i \pm d_j \leqslant 10 ^ 6
$$
可以发现
观察到发生这个问题的本质是因为在两个矩阵的相同位置出现了相同的符号
$$\begin{bmatrix}
+1 & -1 & +1 & -1 \\
-1 & +1 & -1 & +1 \\
+1 & -1 & +1 & -1 \\
-1 & +1 & -1 & +1 \\
\end{bmatrix}
\rm and
\begin{bmatrix}
-1 & +1 & -1 & +1 \\
+1 & -1 & +1 & -1 \\
-1 & +1 & -1 & +1 \\
+1 & -1 & +1 & -1 \\
\end{bmatrix}
$$
于是此时就可以使用差分约束的常规求解方式了
使用 $\rm SPFA$ 的时间复杂度为 $\Theta[n ^ 2 (n + m)]$
$\rm Code$
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 300 + 10, M = N * N << 1;
int T, n, m, a[N][N], b[N][N];
int last[N << 1], to[M], Next[M], W[M], tot;
int vis[N << 1], dis[N << 1], num[N << 1];
queue <int> Q;
void Link (int u, int v, int w) {
to[++tot] = v, W[tot] = w, Next[tot] = last[u], last[u] = tot;
}
signed main () {
scanf("%lld", &T); while (T--) {
scanf("%lld%lld", &n, &m);
tot = 0;
for (int i = 0; i <= n + m; i++)
last[i] = num[i] = 0, vis[i] = false, dis[i] = 1e9;
while (!Q.empty()) Q.pop();
for (int i = 2; i <= n; i++)
for (int j = 2; j <= m; j++)
scanf("%lld", &b[i][j]);
for (int i = 1; i <= n; i++) a[i][1] = 0;
for (int i = 1; i <= m; i++) a[1][i] = 0;
for (int i = 2; i <= n; i++)
for (int j = 2; j <= m; j++)
a[i][j] = b[i][j] - a[i - 1][j] - a[i][j - 1] - a[i - 1][j - 1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if ((i + j) & 1) Link(n + j, i, a[i][j]), Link(i, n + j, 1e6 - a[i][j]);
else Link(i, n + j, a[i][j]), Link(n + j, i, 1e6 - a[i][j]);
for (int i = 1; i <= n + m; i++) Link(0, i, 0);
dis[0] = 0, Q.push(0), vis[0] = 1;
bool flag = false;
while (!Q.empty()) {
int u = Q.front();
if (++num[u] > 10) { flag = true; break; }
Q.pop(), vis[u] = false;
for (int i = last[u]; i; i = Next[i])
if (dis[to[i]] > dis[u] + W[i]) {
dis[to[i]] = dis[u] + W[i];
if (!vis[to[i]]) Q.push(to[i]), vis[to[i]] = true;
}
}
if (flag) { puts("NO"); continue; }
puts("YES");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if ((i + j) & 1) a[i][j] += dis[n + j] - dis[i];
else a[i][j] += dis[i] - dis[n + j];
printf("%lld ", a[i][j]);
}
puts("");
}
}
return 0;
}