1. 程式人生 > 其它 >查分約束

查分約束

C - 天平

 https://cn.vjudge.net/contest/263026#problem/C

 你有n個砝碼,均為1克,2克或者3克。你並不清楚每個砝碼的重量,但你知道其中一些砝碼重量的大小關係。
你把其中兩個砝碼A和B放在天平的左邊,需要另外選出兩個砝碼放在天平的右邊。問:有多少種選法使得天平的左
邊重(c1)、一樣重(c2)、右邊重(c3)?(只有結果保證惟一的選法才統計在內)

Input

  第一行包含三個正整數n,A,B(1<=A,B<=N,A和B不相等)。砝碼編號為1~N。以下n行包含重量關係矩陣,
其中第i行第j個字元為加號“+”表示砝碼i比砝碼j重,減號“-”表示砝碼i比砝碼j輕,等號“=”表示砝碼i和砝


碼j一樣重,問號“?”表示二者的關係未知。存在一種情況符合該矩陣

Output

  僅一行,包含三個整數,即c1,c2和c3。

Sample Input6 2 5 ?+???? -?+??? ?-???? ????+? ???-?+ ????-?

Sample Output1 4 1Hint

 

【資料規模】 4<=n<=50

題解:

給出A 和 B 找出C和 D 求A+B>C+D  A+B=C+D  A+B<C-D 

由 A+B>C+D   ->   A-C>D-B   ->   A-C的最小值>D-B的最大值    就能想到了差分約束

於是我們要差分約束把每兩個砝碼的最大差值和最小差值算出來 之後暴力列舉即可

 
#include<bits/stdc++.h>
using namespace std;
char s[60];
int mx[60][60], mi[60][60];

int main(){
    int n, A, B;
    scanf("%d%d%d", &n, &A, &B);
    for(int i = 1; i <= n; i++){
        scanf("%s", s + 1);
        for(int j = 1; j <= n; j++){
            
if(i == j || s[j] == '=') mx[i][j] = mi[i][j] = 0; else if(s[j] == '-') mx[i][j] = -1, mi[i][j] = -2; else if(s[j] == '+') mx[i][j] = 2, mi[i][j] = 1; else mx[i][j] = 2, mi[i][j] = -2; } } for(int k = 1; k <= n; k++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){ if(i == k || j == k || i == j)continue; mx[i][j] = min(mx[i][j], mx[i][k] + mx[k][j]); mi[i][j] = max(mi[i][j], mi[i][k] + mi[k][j]); } long long day = 0, xiaoy = 0, dengy = 0; for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++){ if(i == A || j == A || i == B || j == B)continue; if(mi[i][A] > mx[B][j] || mi[i][B] > mx[A][j])xiaoy++; if(mx[i][A] < mi[B][j] || mx[i][B] < mi[A][j])day++; if((mx[i][A] == mi[i][A] && mi[j][B] == mx[j][B] && mx[i][A] == mx[B][j]) || (mx[j][A] == mi[j][A] && mi[B][i] == mx[B][i] && mx[j][A] == mx[B][i]))dengy++; } cout<<day<<" "<<dengy<<" " <<xiaoy<<endl; }
View Code