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

\(\texttt{Introduction}\)

差分约束好题,感觉是 \(\texttt{day1}\) 质量最高的一道题。

\(\texttt{Solution}\)

为了研究方便,现将矩形定为 \(4\times 4\) 的,然后再进行拓展。

首先这道题有一个非常重要的结论,就是我们只要知道第一行以及第一列,我们就可以推出整个矩形,那么我们只是可以列出这么一个表格:

A \(X_2\) \(X_3\) \(X_4\)
\(Y_2\) B(1,1)-X(2)-Y(2)-A B(1,2)-B(1,1)+Y(2)+A-X(3) B(1,3)-B(1,2)+B(1,1)-Y(2)-A-X(4)
\(Y_3\) B(2,1)-B(1,1)+X(2)+A-Y(3) B(2,2)-B(2,1)-A+Y(3)-B(1,2)+B(1,1)+X(3)
\(Y_4\)

那么做到这里我们考虑将与 \(B\) 有关的全部设成常数,记作 \(C(i,j)\) 。

那么现在就是对于每一对 \((i,j)\) 存在下列不等式:

\[C(i,j)+A\times (-1)^{i+j-1}+X_i\times (-1)^{j-1}+Y_j\times (-1)^{i-1}\ge 0 \]

\[C(i,j)+A\times (-1)^{i+j-1}+X_i\times (-1)^{j-1}+Y_j\times (-1)^{i-1}\le 10^6 \]

\[0\le A \le 10^6 \]

那么如果不考虑 \(A\) 的话这道题就是一道模板的差分约束,但是我们现在要知道这个 \(A\) 的值,那么是否可以通过微调实现?

我们根据 \(C(i,j)\) 再列一个表格。

A \(X_2\) \(X_3\) \(X_4\)
\(Y_2\) C(2,2)-X(2)-Y(2)-A C(2,3)+Y(2)+A-X(3) C(2,4)-Y(2)-A-X(4)
\(Y_3\) C(3,2)+X(2)+A-Y(3) C(3,3)-A+Y(3)+X(3) C(3,4)+A+X(4)-Y(3)
\(Y_4\) C(4,2)-X(2)-A-Y(4) C(4,3)-X(3)+A+Y(4) C(4,4)-X(4)-A-Y(4)

那么我们考虑假设:

\[E(i)=A+X(i),i为偶数;E(i)=A-X(i),i为奇数 \]

\[F(i)=-Y(i),i为偶数;F(i)=Y(i),i为奇数 \]

\[E(i)-10^6 \le A \le E(i),E(i) \le A \le E(i)+10^6 \]

#include <bits/stdc++.h>
using namespace std;
inline long long read() {
	long long x=0,f=1;
	char ch=getchar();
	while ((!isdigit(ch))&&(ch!='-')) ch=getchar();
	if (ch=='-') f=-1,ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	return x*f;
}
vector<pair<int,long long>> V[1010];
bool flag,vis[1010];
long long x,tag[1010],t,w,f1[10001010],Testing,n,m,i,j,cnt;
long long y,B[310][310],C[310][310],Answ[310][310],AA,dis[1010];
inline void add(int x,int y,int z) {
	V[x].push_back(make_pair(y,z));
}
int main() {
	//freopen("data.in","r",stdin);
	//freopen("TLE.out","w",stdout);
	Testing=read();
	for (; Testing; Testing--) {
		n=read();
		m=read();
		for (i=1; i<n; i++)for (j=1; j<m; j++) B[i][j]=read();
		for (i=2; i<=n; i++)
			for (j=2; j<=m; j++)
				C[i][j]=B[i-1][j-1]-C[i-1][j]-C[i][j-1]-C[i-1][j-1];
		
		//n+m-2个点
		for (i=2; i<=m; i++)
			for (j=2; j<=n; j++) {
				if (((i+j)&1)==0) {
					//0<=C(i,j)-E(i)+F(j)
					//E(i)-F(j)<=C(i,j)
					add(j+m,i,C[j][i]);
					//C(i,j)-E(i)+F(j)<=1000000
					//F(j)-E(i)<=1000000-C(i,j)
					add(i,j+m,1000000-C[j][i]);
				}
				if (((i+j)&1)==1) {
					//0<=C(i,j)+E(i)-F(j)<=1000000
					//F(j)-E(i)<=C(i,j)
					add(i,j+m,C[j][i]);
					add(j+m,i,1000000-C[j][i]);
				}
			}
		//E(i)>=0
		//E(0)-E(i)<=0
		//E(i)<=2000000
		//E(i)-E(0)<=2000000
		//E(i)+1000000>=0
		//E(i)>=-1000000
		//E(0)-E(i)<=1000000
		//E(i)<=1000000
		//E(i)-E(0)<=1000000
		//
		for (i=2; i<=m; i++)
			if (!(i&1)) {
				add(i,0,0);
				add(0,i,2000000);
			} else {
				add(i,0,1000000);
				add(0,i,1000000);
			}
		//E(0)-F(i)>=0
		//F(i)-E(0)<=0
		//F(i)-E(0)>=0
		//E(0)-F(i)<=0
		//-F(i)>=0
		//
		//-F(i)<=1000000
		//E(0)-F(i)<=1000000
		//F(i)<=1000000
		//F(i)-E(0)<=1000000
		//-F(i)>=0
		//F(i)-E(0)<=0
		for (i=2; i<=n; i++)
			if (!(i&1)) add(0,i+m,0),add(i+m,0,1000000);
			else add(i+m,0,0),add(0,i+m,1000000);
		for (i=2; i<=m; i++)
			for (j=i+1; j<=m; j++) {
				if ((!(i&1))&&(!(j&1))) {
					//E(i)-1000000<=E(j)
					//E(j)-1000000<=E(i)
					//E(i)-E(j)<=1000000,E(j)-E(i)<=1000000
					add(j,i,1000000);
					add(i,j,1000000);
				}
				if ((!(i&1))&&(j&1)) {
					//E(i)-1000000<=E(j)+1000000
					//E(i)-E(j)<=2000000
					//E(j)<=E(i)
					//E(j)-E(i)<=0
					add(j,i,2000000);
					add(i,j,0);
				}
				if ((i&1)&&(!(j&1))) {
					add(i,j,2000000);
					add(j,i,0);
				}
				if ((i&1)&&(j&1)) {
					//E(i)<=E(j)+1000000
					//E(j)<=E(i)+1000000
					//E
					add(j,i,1000000);
					add(i,j,1000000);

				}
			}
		for (i=0; i<=n+m+2; i++) dis[i]=1e18,tag[i]=0,vis[i]=false;
		t=1;
		w=1;
		dis[0]=0;
		f1[1]=0;
		flag=false;
		int sum = 0;
		while (t<=w) {
			if (flag) break;
			vis[f1[t]]=false;
			for (auto i:V[f1[t]])
			    {
				x=i.first;y=i.second;
				if (dis[x]>dis[f1[t]]+y) 
					{
						dis[x]=dis[f1[t]]+y;
						if ((tag[x]=tag[f1[t]]+1)>=n+m-1) {
							flag=true;
							break;
						}
						if (vis[x]==false) {
							w++;
							f1[w]=x;
							vis[x]=true;
						}
					}
				}
			t++;
		}
		for (i=0;i<=n+m+2;i++) V[i].clear();
		if (flag) puts("NO");
		else {
			puts("YES");
			AA=1e18;
			for (i=2; i<=m; i++)
				if (i % 2==0) AA=min(AA,dis[i]);
				else AA=min(AA,dis[i]+1000000);
		    AA=min(AA,(long long)1000000);
			Answ[1][1]=AA;
			for (i=2; i<=m; i++)
				if (i % 2==0)
					Answ[1][i]=dis[i]-AA;
				else Answ[1][i]=AA-dis[i];
			for (i=2; i<=n; i++)
				if (i % 2==1) Answ[i][1]=dis[i+m];
				else Answ[i][1]=-dis[i+m];
			for (i=2; i<=n; i++)
				for (j=2; j<=m; j++)
					Answ[i][j]=B[i-1][j-1]-Answ[i-1][j]-Answ[i-1][j-1]-Answ[i][j-1];
			for (i=1; i<=n; i++) {
				for (j=1; j<=m; j++)
				    {
					printf("%d ",Answ[i][j]);
				}
				puts("");
			}
		}
	}
	return 0;
}

被卡常了 /ll

woc,前向星竟然比不过邻接表。

上一篇:【clickhouse】clickhouse查询语句之simple


下一篇:(转)Unity 3D手游对不同分辨率屏幕的UI自适应