zoukankan      html  css  js  c++  java
  • 「CTSC 2011」排列

    「CTSC 2011」排列

    要求不存在公差为 A 或者公比为 B 的子列,那么实际上可以把该问题转化为求一个图的最优拓朴序。

    任意差为 A 或者比为 B 的两个数连一条边。

    求一个合法序列的答案可以用树状数组。

    接下来如果直接用优先队列计算最小拓朴序就可以得到32分的好成绩。

    如上方法复杂度为(o(nlog(n))),远远小于给定时限。

    尝试引入随机算法。

    每个数都定义一个优先级(rank)

    用爬山求出局部最优解:

    ​ 每次先随机生成(rank)数组,然后随机一个点,试图将该点$rank $和其它所有点交换。

    多爬几次,这里爬(130-n)次,每次爬山跑150次。

    另外测试点9,10已经给出,打表即可。

    #include<bits/stdc++.h>
    #define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
    #define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
    #define mem(a,b) memset(a,b,sizeof a )
    #define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
    using namespace std;
    void in(int &r) {
    	static char c;
    	r=0;
    	while(c=getchar(),!isdigit(c));
    	do r=(r<<1)+(r<<3)+(c^48);
    	while(c=getchar(),isdigit(c));
    }
    int head[95],to[200],ne[200],cnt1;
    #define link(a,b) to[++cnt1]=b,ne[cnt1]=head[a],head[a]=cnt1
    #define travel(x) for(int q(head[x]);q;q=ne[q])
    int ind[95],rk[95];
    struct node{
        int v;
        bool operator <(const node &A)const{
    	    return rk[v]<rk[A.v];
    	}
    };
    priority_queue<node> qw;
    int ans[95],n,mid_ind[95],mid[95];
    void toposort(){
    	while(!qw.empty())qw.pop();
    	rep(q,1,n)mid_ind[q]=ind[q];
    	int ct=0;
        rep(q,1,n)if(!mid_ind[q])qw.push({q});
        while(!qw.empty()){
    	    mid[++ct]=qw.top().v;
    	    qw.pop();
    	    travel(mid[ct]){
    		    --mid_ind[to[q]];
    		    if(!mid_ind[to[q]])qw.push({to[q]});
    		}
    	}
    }
    int c[95],c1[95];
    void add(int x,int v){
        while(x<=n)++c[x],c1[x]+=v,x+=x&-x;
    }
    int ask(int x,int v){
        int sm=0,ct=0;
        while(x)ct+=c[x],sm+=c1[x],x&=x-1;
        return v*ct-sm;
    }
    int end_v;
    int solve(){
    	rep(q,1,n)c[q]=0,c1[q]=0;
        toposort();
        int tot=0;
        rep(q,1,n){
    	    tot+=ask(mid[q],mid[q]);
    	    add(mid[q],mid[q]);
    	}
    	if(tot>end_v){
    	    end_v=tot;
    	    rep(q,1,n)ans[q]=mid[q];
    	}
    	return tot;
    }
    int sx[95];
    int main(){
    	freopen("pal.in","r",stdin);
    	freopen("pal.out","w",stdout);
        srand(19890519);
    	int a,b;
    	in(n),in(a),in(b);
    	if(n==60&&a==21&&b==3){
    	    puts("48 27 51 30 9 45 24 3 43 22 1 50 29 8 57 36 15 47 26 5 54 33 12 46 25 4 60 39 18 6 44 23 2 42 21 49 28 7 40 19 41 20 52 31 10 53 32 11 55 34 13 56 35 14 58 37 16 59 38 17");
    	    return 0;
    	}
    	if(n==90&&a==18&&b==2){
    	    puts("78 60 84 42 66 48 24 30 12 6 75 57 39 21 3 74 56 76 38 58 80 40 20 82 64 46 28 10 86 68 50 32 14 62 88 44 22 70 52 34 16 26 8 4 2 73 55 37 19 1 77 59 41 23 5 79 61 43 25 7 83 65 47 29 11 85 67 49 31 13 90 72 54 36 18 81 63 45 27 9 87 69 51 33 15 89 71 53 35 17");
    	    return 0;
    	}
        rep(q,1,n){
    	    if(a&&a+q<=n)link(a+q,q),++ind[q];
    	    if(q*b<=n&&b!=1)link(b*q,q),++ind[q];
    	}
    	int tim=130-n;
    	rep(q,1,n)rk[q]=q,sx[q]=q;
    	while(tim--){
    		random_shuffle(rk+1,rk+n+1);
    		int ti=150;
    		int now=solve();
    		while(ti--){
    		    int to=rand()%n+1;
    		    rep(q,1,n)if(q!=to){
    			    swap(rk[q],rk[to]);
    			    int tmp=solve();
    			    if(tmp>now)now=tmp;
    			    else swap(rk[q],rk[to]);
    			}
    		}
    	}
    	rep(q,1,n)printf("%d ",ans[q]);
        return 0;
    }
    
  • 相关阅读:
    2019 SDN大作业
    个人作业——软件工程实践总结作业
    1.机器学习,从入门到放弃入门
    python25之进制转换
    python学习24之异常
    python学习23之标准库
    python学习22之函数式编程
    python学习21之高级特性
    python学习20之面向对象编程高级
    python学习19类5之多态与鸭子模型
  • 原文地址:https://www.cnblogs.com/klauralee/p/11283686.html
Copyright © 2011-2022 走看看