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

这道题目考场上面一点思路没有,虽然尝试了一下 \(75pts\) ,但最后就打了个暴力。。。

考出来后听到同学说什么最短路,差分约束?直接蒙圈,跟我说网络流还有点道理,这就不是很懂了。。。

然后现在决定来写一下这道神仙题。

题解

我们发现只要确定了第一行第一列,一定可以确定整一个矩阵。

\[\begin{matrix} a_1 & a_2 & a_3 & a_4 \\ a_5 & b_{1,1}-a_1-a_2-a_5 & b_{1,2}-b_{1,1}+a_1-a_3+a_5 & b_{1,3}-b_{1,2}+b_{1,1}-a_1-a_4-a_5 \\ a_6 & b_{2,1}-b_{1,1}+a_1+a_2-a_6 & b_{2,2}-b_{1,2}-b_{2,1}+b_{1,1}-a_1+a_3+a_6 & b_{2,3}-b_{2,3}-b_{1,3}+b_{1,2}+b_{2,1}-b_{1,1}+a_1+a_4-a_6 \\ a_7 & b_{3,1}-b_{2,1}+b_{1,1}-a_1-a_2-a_7 & b_{3,2}-b_{2,2}-b_{3,1}+b_{2,1}+b_{1,2}-b_{1,1}+a_1-a_3+a_7 & b_{3,3}-b_{3,2}-b_{2,3}+b_{1,3}+b_{2,2}+b_{3,1}-b_{1,2}-b_{2,1}+b_{1,1}-a_1-a_4-a_7 \\ \end{matrix} \]

然后发现规律很好找,相当于每一个都变成了包含 \(a_1\) 和随机两个 \(a\) 的不等式。

我们现在干脆把一个位置中所有的 \(b_{i,j}\) 用一个变量 \(c_{i,j}\) 来代替,矩阵就变成了下面的这个。

\[\begin{matrix} a_1 & a_2 & a_3 & a_4 \\ a_5 & c_{1,1}-a_1-a_2-a_5 & c_{1,2}+a_1-a_3+a_5 & c_{1,3}-a_1-a_4-a_5 \\ a_6 & c_{2,1}+a_1+a_2-a_6 & c_{2,2}-a_1+a_3+a_6 & c_{2,3}+a_1+a_4-a_6 \\ a_7 & c_{3,1}-a_1-a_2-a_7 & c_{3,2}+a_1-a_3+a_7 & c_{3,3}-a_1-a_4-a_7 \\ \end{matrix} \]

我们发现我们现在遇到了两个问题:

  1. 每一个式子里都存在一个 \(a_1\) ,但是我们没有办法消去,我们需要实现对于 \(a_1\) 的枚举?
  2. 如果在确定 \(a_1\) 的情况下,对于一个位置存在的不等式,他的种类也有许多,我们不好直接使用。

对于第二个问题好像我有解决的方案,你考虑把一些位置变成负数,这样的话就可以满足一正一负的不等式了。

\[\begin{matrix} a_1 & -a_2 & a_3 & -a_4 \\ a_5 & c_{1,1}-a_1+a_2-a_5 & c_{1,2}+a_1-a_3+a_5 & c_{1,3}-a_1+a_4-a_5 \\ -a_6 & c_{2,1}+a_1-a_2+a_6 & c_{2,2}-a_1+a_3-a_6 & c_{2,3}+a_1-a_4+a_6 \\ a_7 & c_{3,1}-a_1+a_2-a_7 & c_{3,2}+a_1-a_3+a_7 & c_{3,3}-a_1+a_4-a_7 \\ \end{matrix} \]

这样就行了。

刚刚偷偷复习了一下差分约束。

然后感觉这个 \(a_1\) 消不掉啊。。。

我们发现可以把第一列全部换成和 \(a_1\) 的关系。

\[a_1+a_5=d_5\\ a_1+a_6=d_6\\ a_1+a_7=d_7\\ \begin{matrix} a_1 & -a_2 & a_3 & -a_4 \\ d_5-a_1 & c_{1,1}+a_2-d_5 & c_{1,2}-a_3+d_5 & c_{1,3}+a_4-d_5 \\ a_1-d_6 & c_{2,1}-a_2+d_6 & c_{2,2}+a_3-d_6 & c_{2,3}-a_4+d_6 \\ d_7-a_1 & c_{3,1}+a_2-d_7 & c_{3,2}-a_3+d_7 & c_{3,3}+a_4-d_7 \\ \end{matrix} \]

然后就好像可以搞差分约束了。

被判负环搞没了。

\(\huge{😭😭😭😭😭😭😭😭😭😭😭😭😭😭}\)

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=305;
int n,m,a[N][N],b[N][N],c[N][N],d[N<<1],mp[N<<1][N<<1];
deque<int> q;int tag[N<<1],cnt[N<<1];
inline int read(){
	char c=getchar();int x=0;
	while(c<'0'||'9'<c) c=getchar();
	while('0'<=c&&c<='9') x=x*10+c-'0',c=getchar();
	return x;
}
void init(){
	memset(cnt,0,sizeof(cnt));
	memset(tag,0,sizeof(tag));
	while(!q.empty()) q.pop_back();
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=n+m;++i){
		for(int j=1;j<=n+m;++j)
		mp[i][j]=1e18+7;
	}
	for(int i=1;i<n;++i){
		for(int j=1;j<m;++j){
			b[i][j]=read();
			c[i][j]=b[i][j]-c[i-1][j]-c[i][j-1]-c[i-1][j-1];
		}
	}
	for(int i=1;i<n;++i){
		for(int j=1;j<m;++j){
			if((i^j)&1) mp[i+m][j+1]=c[i][j],mp[j+1][i+m]=1e6-c[i][j];
			else mp[i+m][j+1]=1e6-c[i][j],mp[j+1][i+m]=c[i][j];
		}
	}
	for(int i=1;i<n;++i){
		if(i&1) mp[1][i+m]=1e6,mp[i+m][1]=0;
		else mp[1][i+m]=0,mp[i+m][1]=1e6;
	}
	for(int i=1;i<=m;++i){
		if(i&1) mp[n+m][i]=1e6,mp[i][n+m]=0;
		else mp[n+m][i]=0,mp[i][n+m]=1e6;
	}
	for(int i=1;i<n+m;++i) d[i]=1e18+7;
	d[n+m]=0,q.push_back(n+m),tag[n+m]=true,cnt[n+m]=0;
	while(!q.empty()){
		int u=q.front();q.pop_front(),tag[u]=false;
		for(int v=1;v<=n+m;++v){
			if(d[v]<=d[u]+mp[u][v]) continue;
			d[v]=d[u]+mp[u][v],cnt[v]=cnt[u]+1;
			if(cnt[v]>n+m) return printf("NO\n"),void();
			if(!tag[v]){
				if(q.empty()) q.push_back(v);
				else if(d[v]<d[q.front()]) q.push_front(v);
				else q.push_back(v);
				tag[v]=true,cnt[v]++;
			}
		}
	}
	for(int i=1;i<=m;++i) a[1][i]=(i&1)?d[i]:-d[i];
	for(int i=1;i<n;++i) a[i+1][1]=(i&1)?d[i+m]-d[1]:d[1]-d[i+m];
	for(int i=1;i<n;++i){
		for(int j=1;j<m;++j)
		a[i+1][j+1]=b[i][j]-a[i+1][j]-a[i][j+1]-a[i][j];
	}
	printf("YES\n");
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j)
		printf("%lld ",a[i][j]);
		printf("\n");
	}
}
signed main(){
	int T;cin>>T;
	while(T--) init(),solve();
	return 0;
}
posted @ 2021-04-22 12:05  Point_King  阅读(107)  评论(0)    收藏  举报