洛谷P2474 [SCOI2008] 天平 题解

step1

首先我们设 \(mn_{i,j}\)为砝码 \(i\) -砝码 \(j\) 的最小值(下文以\(a_i\)\(a_j\)代替)。
\(mx_{i,j}\)\(a_i-a_j\)的最大值。

当设\(a_i\)\(a_j\)的关系为\(g_{i,j}\)

\(g_{i,j}\)\(+\)时,

\(a_i\) \(a_j\) \(a_i-a_j\)
3 1 2
2 1 1
3 2 1

明显,\(mx_{i,j}=2\),\(mn_{i,j}=1\)

\(g_{i,j}\)\(-\)时,

\(a_i\) \(a_j\) \(a_i-a_j\)
1 3 -2
1 2 -1
2 3 -1

\(mx_{i,j}=-1\),\(mn_{i,j}=-2\)
\(g_{i,j}\)\(=\)
\(\because a_i=a_j\)
\(\therefore mn_{i,j}=mn_{i,j}=0\)

最后当\(g_{i,j}\)\(?\)
\(mx_{i,j}=2\),\(mn_{i,j}=-2\)(相当于\(+\)\(-\))的结合
综上

\[\begin{cases} mx_{i,j}=2,mn_{i,j}=1 & g_{i,j}为+\\ mx_{i,j}=-1,mn_{i,j}=-2 & g_{i,j}为-\\ mx_{i,j}=0,mn_{i,j}=0 & g_{i,j}为=\\ mx_{i,j}=2,mn_{i,j}=-2 & g_{i,j}为?\\ \end{cases} \]

step2

我们知道了\(mx\)\(mn\)的值,接下来题面说要唯一情况,所以我们要差分约束
\(mn_{i,j}\)记录的是\(a_i-a_j的最小差值\)。那我们可以找一个\(k\)

\[mn_{i,j}=a_i-a_j\\ \hspace{7em} =a_i-a_k+a_k-a_j\\ \hspace{5.7em}=mn_{i,k}+mn_{k,j} \]

因为题目要求唯一答案,\(mn_{i,j}\)要尽可能大
所以

\[mn_{i,j}=\max\limits_{k=1}^{n} mn_{i,k}+mn_{k,j} \]

同理

\[mx_{i,j}=\min\limits_{k=1}^{n} mx_{i,k}+mx_{k,j} \]

step3

\(A+B>a_i+a_j\)

\[A+B>a_i+a_j\\ \hspace{3em}A-a_i+B-a_j>0\rightarrow mn_{A,i}+mn_{B,j}>0\\ \hspace{3em}A-a_j+B-a_i>0\rightarrow mn_{A,j}+mn_{B,i}>0\\ \]

\(A+B<a_i+a_j\)类似

\[A+B<a_i+a_j\\ \hspace{3em}A-a_i+B-a_j<0\rightarrow mx_{A,i}+mx_{B,j}<0\\ \hspace{3em}A-a_j+B-a_i<0\rightarrow mx_{A,j}+mx_{B,i}<0\\ \]

\(A+B=a_i+a_j\)有点不同。因为既要满足\(mx\)相等,又要满足\(mn\)相等。

\[\hspace{-15em}\textcircled{1}\\ A+B=a_i+a_j\\ \hspace{8.2em}{A-a_i+B-a_j=0}\rightarrow{mx_{A,i}=mn_{A,i},mx_{B,j}=mn_{B,j}}\\ \hspace{-4.3em}{{A,i}+{B,j}=0} \]

\[\hspace{-15em}\textcircled{2}\\ A+B=a_i+a_j\\ \hspace{8.2em}{A-a_j+B-a_i=0}\rightarrow{mx_{A,j}=mn_{A,j},mx_{B,i}=mn_{B,i}}\\ \hspace{-4.3em}{{A,j}+{B,i}=0} \]

\(\because mx_{i,j}=mn_{i,j}\)
\(\therefore\)\(mx\) \(mn\)都行

step4

#include<bits/stdc++.h>
using namespace std;
const int N=55;
char g[N][N];
int mx[N][N],mn[N][N];
int n,A,B;
void csh()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(g[i][j]=='+')mx[i][j]=2,mn[i][j]=1;
			if(g[i][j]=='-')mx[i][j]=-1,mn[i][j]=-2;
			if(g[i][j]=='=')mx[i][j]=mn[i][j]=0;
			if(g[i][j]=='?')mx[i][j]=2,mn[i][j]=-2;
			if(i==j)mx[i][j]=mn[i][j]=0;
		}
	}
}
int main()
{
	cin>>n>>A>>B;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>g[i][j];
		}
	}
	csh();
	for(int k=1;k<=n;k++)
	{	
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				mn[i][j]=max(mn[i][j],mn[i][k]+mn[k][j]);
				mx[i][j]=min(mx[i][j],mx[i][k]+mx[k][j]);
			}
		}
	}
	int c1=0,c2=0,c3=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			if(i==A||i==B||j==A||j==B)continue;
			if(mn[A][i]+mn[B][j]>0||mn[A][j]+mn[B][i]>0)c1++;
			if(mx[A][i]+mx[B][j]<0||mx[A][j]+mx[B][i]<0)c3++;
			if(mn[A][i]==mx[A][i]&&mn[B][j]==mx[B][j]&&mn[A][i]+mn[B][j]==0)c2++;
			else if(mn[A][j]==mx[A][j]&&mn[B][i]==mx[B][i]&&mn[A][j]+mn[B][i]==0)c2++;
		}
	}
	cout<<c1<<' '<<c2<<' '<<c3;
	
	return 0;
}
posted @ 2025-10-20 15:43  NumLuck  阅读(12)  评论(0)    收藏  举报