P7515 [省选联考 2021 A 卷] 矩阵游戏

Sol

如果没有对于里面数字的限制是简单的,直接另最后一行最后一列都是 \(0\),然后倒推即可。

注意到如果以 \(\{+x,-x,+x,-x\}\) 的形式,\(b\) 数组不会改变。

考虑给第 \(i\) 行交替加减 \(r_i\),第 \(j\) 列交替加减 \(c_j\),那么修改的矩阵为:

\(\left(\begin{matrix}r_1+c_1&-r_1+c_2&r_1+c_3&\ldots\\r_2-c_1&-r_2-c_2&r_2-c_3&\ldots\\r_3+c_1&-r_3+c_2&r_3+c_3&\ldots\\\vdots&\vdots&\vdots&⋱\\\end{matrix}\right)\)

注意这里面形式不一,考虑把负号移动到 \(r_i\)\(c_j\) 内,如果把 \(i\) 是偶数的行,\(r_i\gets -r_i\)\(j\) 是奇数的列,\(c_j\gets -c_j\)

然后就全部都是两个数相减的了,跑差分约束即可。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define eb emplace_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
#define debug(x) cerr << #x << ' ' << x << endl
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	if (!a) return 0;
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
#define int LL
const int N = 310;
int n,m;
int a[N][N],b[N][N];
vector <PII> g[2 * N];
int d[2 * N];
int cnt[2 * N];
bool st[2 * N];
void mian () {
	cin >> n >> m;
	for (int i = 1;i <= n + m;i++) g[i].clear ();
	for (int i = 1;i <= n - 1;i++) for (int j = 1;j <= m - 1;j++) cin >> b[i][j];
	for (int i = 1;i <= n;i++) for (int j = 1;j <= m;j++) a[i][j] = 0;
	for (int i = n - 1;i >= 1;i--) for (int j = m - 1;j >= 1;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++) {
			int maxx = 1000000 - a[i][j],minx = -a[i][j];
			if (!((i + j) & 1)) g[i].pb ({j + n,-minx}),g[j + n].pb ({i,maxx});
			else g[i].pb ({j + n,maxx}),g[j + n].pb ({i,-minx});
		}
	}
	queue <int> q;
	for (int i = 1;i <= n + m;i++) d[i] = 1e18,st[i] = 0,cnt[i] = 0;
	d[1] = 0;
	q.push (1);
	while (q.size ()) {
		int u = q.front ();
		q.pop ();
		st[u] = 0;
		for (auto [v,w] : g[u]) {
			if (d[v] > d[u] + w) {
				d[v] = d[u] + w;
				cnt[v] = cnt[u] + 1;
				if (cnt[v] > n + m) {
					puts ("NO");
					return ;
				}
				if (!st[v]) {
					q.push (v);
					st[v] = 1;
				}
			}
		}
	}
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) {
			if (i + j & 1) a[i][j] += -d[i] + d[j + n];
			else a[i][j] += d[i] - d[j + n];
		}
	}
	puts ("YES");
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) cout << a[i][j] << ' ';
		cout << endl;
	}
}
signed main () {
	int T = 1;
	cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-17 19:12  incra  阅读(7)  评论(0)    收藏  举报