zoukankan      html  css  js  c++  java
  • P2474 [SCOI2008]天平

    题目传送门

    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。


    其实这里应该贴代码的,但是我觉得应该要详细的说一下建图。

    1. +对应的是 (i>j ightarrow i-j>0) ,那么可以得到 (minn_{i,j}=1,maxx_{i,j}=1)
    2. -对应的是 (i<j ightarrow j-i>0) , 同理,可得 (minn_{i,j}=-2,maxx_{i,j}=-1)
    3. =对应的是 (i=j) ,显然是 (maxx_{i,j}=minn_{i,j}=0)
    4. ?没有对应,那我们就考虑题里本来的限制 (maxx_{i,j}=2,minn_{i,j}=-2)

    其实这里应该完结撒花的,但是我觉得应该再说一下判断。

    有三个问题:

    1. (A+B>C+D Leftrightarrow A-C>D-B Leftrightarrow A-D>C-B)
    2. (A+B=C+DLeftrightarrow A-C=D-BLeftrightarrow A-D=C-B)
    3. (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;
    }
    
  • 相关阅读:
    HDU 2433 Travel (最短路,BFS,变形)
    HDU 2544 最短路 (最短路,spfa)
    HDU 2063 过山车 (最大匹配,匈牙利算法)
    HDU 1150 Machine Schedule (最小覆盖,匈牙利算法)
    290 Word Pattern 单词模式
    289 Game of Life 生命的游戏
    287 Find the Duplicate Number 寻找重复数
    283 Move Zeroes 移动零
    282 Expression Add Operators 给表达式添加运算符
    279 Perfect Squares 完美平方数
  • 原文地址:https://www.cnblogs.com/jasony/p/13872570.html
Copyright © 2011-2022 走看看