[SCOI2008] 天平
题目描述
你有 n n n 个砝码,均为 1 1 1 克, 2 2 2 克或者 3 3 3 克。你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系。你把其中两个砝码 A 和 B 放在天平的左边,需要另外选出两个砝码放在天平的右边。问:有多少种选法使得天平的左边重( c 1 c_1 c1)、一样重( c 2 c_2 c2)、右边重( c 3 c_3 c3)?(只有结果保证唯一确定的选法才统计在内)
输入格式
第一行包含三个正整数 n n n, A A A, B B B( 1 ≤ A , B ≤ n 1\le A,B\le n 1≤A,B≤n, A ≠ B A\neq B A=B)。
以下
n
n
n 行包含重量关系矩阵,其中第
i
i
i 行第
j
j
j 个字符为加号 +
表示砝码
i
i
i 比砝码
j
j
j 重,减号 -
表示砝码
i
i
i 比砝码
j
j
j 轻,等号 =
表示砝码
i
i
i 和砝码
j
j
j 一样重,问号 ?
表示二者的关系未知。
数据保证至少存在一种情况符合该矩阵。
输出格式
仅一行,包含三个整数,即 c 1 c_1 c1, c 2 c_2 c2 和 c 3 c_3 c3。
样例 #1
样例输入 #1
6 2 5
?+????
-?+???
?-????
????+?
???-?+
????-?
样例输出 #1
1 4 1
样例 #2
样例输入 #2
14 8 4
?+???++?????++
-??=?=???????=
??????????=???
?=??+?==??????
???-???-???-??
-=????????????
-??=???=?-+???
???=+?=???????
??????????????
??????+???????
??=???-????-??
????+?????+???
-?????????????
-=????????????
样例输出 #2
18 12 11
提示
4 ≤ n ≤ 50 4\le n\le 50 4≤n≤50。
#include<bits/stdc++.h>
using namespace std;
int n,A,B,maxd[100][100],mind[100][100],l,m,r;
char c;
int main(){
// memset(mind,0x3f,sizeof(mind));
scanf("%d%d%d",&n,&A,&B);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>c;
if(c=='='||i==j) maxd[i][j]=mind[i][j]=0;
else if(c=='+') maxd[i][j]=2,mind[i][j]=1;
else if(c=='-') maxd[i][j]=-1,mind[i][j]=-2;
else if(c=='?') maxd[i][j]=2,mind[i][j]=-2;
}
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
maxd[i][j]=min(maxd[i][j],maxd[i][k]+maxd[k][j]);
mind[i][j]=max(mind[i][j],mind[i][k]+mind[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(i==A||i==B) break;
if(j==A||j==B) continue;
if(mind[A][i]>maxd[j][B]||mind[A][j]>maxd[i][B]) l++;
if(mind[A][i]==maxd[A][i]&&maxd[A][i]==mind[j][B]&&mind[j][B]==maxd[j][B]) m++;
else if(mind[A][j]==maxd[A][j]&&maxd[A][j]==mind[i][B]&&mind[i][B]==maxd[i][B]) m++;
if(maxd[A][i]<mind[j][B]||maxd[A][j]<mind[i][B]) r++;
}
}
printf("%d %d %d",l,m,r);
return 0;
}