[SCOI2008]天平

本题加深了对差分约束的理解,并不是绝对的模板题目,但是其核心还是最短路/最长路

砝码间的关系

  1. \(i<j\): 由此可以得到\(1\le i+1\le j\le 3\),即\(1\le j-i\le 2\)

  2. \(i=j\): \(j-i=0\)

  3. \(i>j\): \(-1\le j-i\le -2\)

  4. \(i\)和\(j\)关系未知: \(-2\le j-i\le 2\)

得到砝码之间的所有关系后,我们可以建图,跑最短路和最长路,从而确定砝码的上下界

天平两边的关系

\(A+B<C_i+D_J(i\ne j)\)

通过变换,可以得到两个不等式关系:

\(A-C_i<D_j-B\)和\(A-D_j<C_i-B\)

若想这两个式子恒成立,那么必定满足\(\max(A-C_i)<\min(D_j-B)\)或\(\max(A-D_j)<min(C_i-B)\),统计符合条件的情况即可

\(A+B=C_i+D_J(i\ne j)\)

类似上面的形式,统计满足\(\max(A-C_i)=\min(A-C_i)=\max(D_j-B)=\min(D_j-B)\)或\(\max(A-D_j)=\min(A-D_j)=\max(C_i-B)=\min(C_i-B)\)的情况

\(A+B>C_i+D_J(i\ne j)\)

同理,统计满足\(\min(A-C_i)>\max(D_j-B)\)或\(\min(A-D_j)>\max(C_i-B)\)的情况

代码

#include <bits/stdc++.h>
using namespace std;

inline void Max(int &a, int b) { a = a > b ? a : b; }
inline void Min(int &a, int b) { a = a < b ? a : b; }

constexpr int N = 55;
int maxd[N][N], mind[N][N];
int n, a, b;
char s[N];

int main() {
  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 (s[j] == '+') {
        maxd[i][j] = 2;
        mind[i][j] = 1;
      } else if (s[j] == '-') {
        maxd[i][j] = -1;
        mind[i][j] = -2;
      } else if (s[j] == '=' or i == j){
        maxd[i][j] = 0;
        mind[i][j] = 0;
      } else {
        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++) {
        Min(maxd[i][j], maxd[i][k] + maxd[k][j]);
        Max(mind[i][j], mind[i][k] + mind[k][j]);
      }
    }
  int c[3] = {0};

  for (int i = 1; i <= n; i++) {
    if (i == a or i == b) continue;
    for (int j = 1; j < i; j++) {
      if (j == a or j == b) continue;
      c[0] += maxd[j][b] < mind[a][i] or maxd[i][b] < mind[a][j];
      c[1] += 
        (maxd[a][i] == mind[a][i] and 
         maxd[j][b] == mind[j][b] and 
         maxd[a][i] == mind[j][b]) or 
        (maxd[a][j] == mind[a][j] and 
         maxd[i][b] == mind[i][b] and 
         maxd[a][j] == mind[i][b]);
      c[2] += maxd[a][i] < mind[j][b] or maxd[a][j] < mind[i][b];
    }
  }

  for (int i : c) printf("%d ", i);

  return 0;
}
上一篇:输出十个数中的最大数(调用函数)


下一篇:一刷117-动态规划-279完全平方数(m)