zoukankan      html  css  js  c++  java
  • 置换群

    poj 3270 Cow Sorting 简单的更换

    如果初始状态是 

    a:2 3 1 5 4 6

    则目标状态为

    b:1 2 3 4 5 6且下标为初始状态中的3 1 2 4 5 6(a[3],a[1]...)

    将置换群写成循环的形式

    (2,3,1),(5,4),6就不用移动了。

    移动方式2种

    1:选循环内最小的数和其它len-1个数交换

    2:选整个序列最小的数和循环内最小的数交换。转到1。再换回来。

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int a[100005],b[100005];
    int hash[100005];
    bool vis[100005];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
            sort(b+1,b+1+n);
            for(int i=1;i<=n;i++) hash[a[i]]=i;
            int ans=0;
            /*
            2 3 1
            1 2 3----id: 3 1 2
            */
            for(int i=1;i<=n;i++)
            {
                if(vis[i]||a[i]==b[i]) continue;
                int id=i,x=a[i],len=0,mins=0x3f3f3f3f,sum=0;
                while(true)
                {
                    sum+=x;
                    mins=min(mins,x);
                    vis[id]=true;
                    x=b[id];
                    id=hash[b[id]];
                    len++;
                    if(x==a[i]) break;
    
                }
                ans+=min(sum-mins+mins*(len-1),(sum-mins+b[1]*(len-1)+2*(b[1]+mins)));
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    

    i位置相应a[i]位置。求相应K次之后的字符串是什么,(k非常大)

    相同和上题一样暴力寻找置换循环。比如

    4 5 3 7 2 8 1 6 10 9 可分成(4,7,1),(5,2),(3),(8,6),(10,9),找到了每块循环的长度len之后

    对每块循环模拟求k%len次即可了。

    代码有点不同,但思想就是这样。

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    int a[205];
    int sum[205];
    char str[205];
    char tmp[205];
    int v[205][205];
    int main()
    {
        int cas,n,k;
        while(scanf("%d",&n)!=EOF&&n)
        {
            for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=0;
            for(int i=1;i<=n;i++)
            {
                int j=a[i];
                if(i==j) {v[i][sum[i]++]=i;continue;}
                v[i][sum[i]++]=i;
                while(i!=j)
                {
                    v[i][sum[i]++]=j;
                    j=a[j];
                }
            }
            while(~scanf("%d",&k)&&k)
            {
                getchar();
                gets(str+1);
                for(int i=strlen(str+1)+1;i<=n;i++) str[i]=' ';
                for(int i=1;i<=n;i++) tmp[ v[i][k%sum[i]] ]=str[i];
                tmp[n+1]='';
                puts(tmp+1);
            }
            puts("");
        }
        return 0;
    }
    


    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    kali linux DDos攻击
    js基础接替上回的作用域
    js基础的知识函数和作用域
    写作是最好的思考
    eclipse 常用操作(转载)
    网页中用jquery validate 验证表单输入项
    eclipse5.5添加反编译插件
    velocity 实现td 中月份的多选框
    LinckedhashMap原理
    api服务端接口安全
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4829119.html
Copyright © 2011-2022 走看看