• [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;
    }
    
  • 相关阅读:
    cuda(2)---方阵乘法
    cuda(1)-imageBlur
    python(6) 字符串操作
    CUDA 编程之Release模式和Debug模式
    20200909 day4 刷题记录
    20200908 day3 刷题记录
    20200906 day1 模拟(一)
    刷题Day 4-6 树形dp三题
    4.28 刷题Day 3 树形dp一题
    DTQ2019-D1T2 括号树 题解
  • 原文地址:https://www.cnblogs.com/FrankOu/p/15855155.html
Copyright © 2020-2023  润新知