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}) ,然后就可以像差分约束一样跑最短路得到这两个数组即可。
至于求最短路的方法,因为 (4leq nleq 50) 并且需要每两个点之间的 (minn,maxx) ,所以考虑用Floyd。
其实这里应该贴代码的,但是我觉得应该要详细的说一下建图。
+
对应的是 (i>j ightarrow i-j>0) ,那么可以得到 (minn_{i,j}=1,maxx_{i,j}=1)-
对应的是 (i<j ightarrow 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+DLeftrightarrow A-C=D-BLeftrightarrow A-D=C-B)
- (A+B<C+DLeftrightarrow A-C<D-BLeftrightarrow 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
",ans1,ans2,ans3);
return 0;
}