置换群

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\n",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]='\0';
            puts(tmp+1);
        }
        puts("");
    }
    return 0;
}


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

posted @ 2015-09-22 15:40  hrhguanli  阅读(341)  评论(0编辑  收藏  举报