zoukankan      html  css  js  c++  java
  • 相邻交换法 & 皇后游戏

    link

    填填初二时研究过的坑(今天初二考试题)。相邻交换法的应用。

    跳过所有前面的简化式子,从 $min{A_i,B_j}$ 与 $min{A_j,B_i}$ 分析。

    若对于所有 $i<j$ ,需要均满足  $min{A_i,B_j} leq min{A_j,B_i}$ 即可。

    但是这个东西可以用来写 $cmp$ 函数吗,答案是不能的。因为 $sort$ 时 $cmp$ 需要满足是严格弱序的。

    严格弱序需要满足:

    非对称性:$A<B land B<A$ 从不成立

    传递性:$A<Bland B<C$ 可以推出 $A<C$  

    不可比性的传递性:令 $A!<Bland B!<Aland B!<Cland C!<B$ 可以推出 $A!<Cland C!<A$  

    即通过条件唯一确定一个序列的顺序。

    而对于上面的比较不满足不可比传递性,如 $(10,10),(6,6),(7,9)$。

    对于之前的国王游戏最后推出的是 $dfrac{a_i}{b_i}<dfrac{a_j}{b_j}$ ,这个东西明显具有严格弱序,故可以直接排序处理。

    而我们如何去处理这道题呢。

    有一个很便捷的做法是对于 $i,j$ 通过 $min{A_i,B_j}$ 与 $min{A_j,B_i}$ 建图(需要满足可以相邻交换),按照其拓扑序排列即可。时间复杂度 $O(n^2)$ 。

    考虑如何去优化这个事情。我们必须添加条件使得在 $min{A_i,B_j} = min{A_j,B_i}$ 时合法(该式子满足传递性)。 由于 $cmp$ 函数的设计必须与 $i,j$ 对称所以猜一猜?

    可以通过花费的时间写程序验证是否合法,即验证传递性与不可比性的传递性。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<climits>
    #define pii pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    int A[4],B[4];bool ff=1;
    bool cmp(int id1,int id2){return min(A[id1],B[id2])==min(A[id2],B[id1])?A[id1]<A[id2]:min(A[id1],B[id2])<min(A[id2],B[id1]);}
    int main(){
        for(int a1=0;a1<=10;a1++)
            for(int b1=0;b1<=10;b1++)
                for(int a2=0;a2<=10;a2++)
                    for(int b2=0;b2<=10;b2++)
                        for(int a3=0;a3<=10;a3++)
                            for(int b3=0;b3<=10;b3++){
                                A[1]=a1,A[2]=a2,A[3]=a3,B[1]=b1,B[2]=b2,B[3]=b3;
                                if(cmp(1,2)&&cmp(2,3)&&!cmp(1,3)) ff=0,printf("WrongAnswer (%d,%d) (%d,%d) (%d,%d)
    ",a1,b1,a2,b2,a3,b3);
                                else if((!cmp(1,2)&&!cmp(2,1))&&(!cmp(2,3)&&!cmp(3,2))&&(cmp(1,3)||cmp(3,1))) ff=0,printf("WrongAnswer (%d,%d) (%d,%d) (%d,%d)
    ",a1,b1,a2,b2,a3,b3);
                            }
        if(ff) printf("Accepted
    ");
        return 0;
    }
    View Code

    使用时根据猜测改变 $cmp$ 函数并适当提高值域即可?若出现 $Accepted$ 即为满足严格弱序,可以直接使用。可以通过上述代码构造反例。

    故可以按照通过上述代码的 $cmp$ 构造,时间复杂度 $O(nlog n)$ 。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<climits>
    #define int long long
    #define pii pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=1e6+11;
    int N,A[MAXN],B[MAXN],C[MAXN],p[MAXN],sum,Maxn;
    bool cmp(int id1,int id2){return min(A[id1],B[id2])==min(A[id2],B[id1])?A[id1]<A[id2]:min(A[id1],B[id2])<min(A[id2],B[id1]);}
    signed main(){
        int cas=read();
        while(cas--){
            N=read(); for(int i=1;i<=N;i++) A[i]=read(),B[i]=read(),p[i]=i; sort(p+1,p+N+1,cmp);sum=0;
            for(int i=1;i<=N;i++) sum+=A[p[i]],C[i]=max(C[i-1],sum)+B[p[i]];
            printf("%lld
    ",C[N]);
        }return 0;
    }
    View Code
  • 相关阅读:
    java 实现图表展示
    jar包可以到maven下载
    eclipse java ee 添加jrebel 工具
    单链表逆序
    面试-准备
    面试基础知识整理
    mysql中CONCAT值为空的问题解决办法
    数字签名 数字证书
    java 内存泄露分析(jmap + MemoryAnalyzer)
    Chrome 控制台console的用法
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/14053901.html
Copyright © 2011-2022 走看看