P2474 [SCOI2008]天平
Solution
我们先考虑其中一个问题: \(A+B>C+D\)
可以简单的移项得到: \(A-C>D-B\) 或 \(A-D>C-B\) 。
看到这里你可能还不知道是什么
再看看数据范围 \(4 \leq n \leq 50\)
我直接暴力
说明我们可以找一些复杂度不太大而且和不等式有关的算法,比如差分约束。
但是普通的差分约束是用来求一组解的,而这里的解不唯一,所以我们可以选择维护元素之间的和差关系。
设 \(minn_{u,v}\) 为 \(u,v\) 的 \(\min\{u-v\}\) , \(maxx_{u,v}\) 为 \(u,v\) 的 \(\max\{u-v\}\) ,然后就可以像差分约束一样跑最短路得到这两个数组即可。
至于求最短路的方法,因为 \(4\leq n\leq 50\) 并且需要每两个点之间的 \(minn,maxx\) ,所以考虑用Floyd。
其实这里应该贴代码的,但是我觉得应该要详细的说一下建图。
+
对应的是 \(i>j\rightarrow i-j>0\) ,那么可以得到 \(minn_{i,j}=1,maxx_{i,j}=1\)-
对应的是 \(i<j\rightarrow j-i>0\) , 同理,可得 \(minn_{i,j}=-2,maxx_{i,j}=-1\)=
对应的是 \(i=j\) ,显然是 \(maxx_{i,j}=minn_{i,j}=0\)?
没有对应,那我们就考虑题里本来的限制 \(maxx_{i,j}=2,minn_{i,j}=-2\)
其实这里应该完结撒花的,但是我觉得应该再说一下判断。
有三个问题:
- \(A+B>C+D \Leftrightarrow A-C>D-B \Leftrightarrow A-D>C-B\)
- \(A+B=C+D\Leftrightarrow A-C=D-B\Leftrightarrow A-D=C-B\)
- \(A+B<C+D\Leftrightarrow A-C<D-B\Leftrightarrow A-D<C-B\)
枚举 \(C,D\) 即可
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=55;
int n,a,b,ans1,ans2,ans3,maxx[N][N],minn[N][N];
char ch[N];
int main(){
scanf("%d%d%d",&n,&a,&b);
a--;b--;
for(int i=0;i<n;i++){
scanf("%s",ch);
for(int j=0;j<n;j++)
if(ch[j]=='='||i==j){
maxx[i][j]=minn[i][j]=0;
}
else if(ch[j]=='-'){
maxx[i][j]=-1;
minn[i][j]=-2;
}
else if(ch[j]=='+'){
maxx[i][j]=2;
minn[i][j]=1;
}
else if(ch[j]=='?'){
maxx[i][j]=2;
minn[i][j]=-2;
}
}
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(i!=j&&j!=k&&i!=j)
maxx[i][j]=min(maxx[i][j],maxx[i][k]+maxx[k][j]),
minn[i][j]=max(minn[i][j],minn[i][k]+minn[k][j]);
for(int c=0;c<n;c++)
for(int d=0;d<c;d++){
if(c==a||c==b||d==a||d==b) continue;
if(minn[a][c]>maxx[d][b]||minn[a][d]>maxx[c][b]) ans1++;
else if((maxx[a][c]==minn[a][c]&&maxx[d][b]==minn[d][b]&&maxx[a][c]==minn[d][b])||(maxx[a][d]==minn[a][d]&&maxx[c][b]==minn[c][b]&&maxx[a][d]==minn[c][b])) ans2++;
else if(maxx[a][c]<minn[d][b]||maxx[a][d]<minn[c][b]) ans3++;
}
printf("%d %d %d\n",ans1,ans2,ans3);
return 0;
}