Sorting a Three-Valued Sequence

排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候。 在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。 写一个程序计算出,给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数。

 

本以为又是什么高端的数学。虽然是,但是并不会。

所以还是朴实做题。。

把原数组叫做A,升序排序后的数组叫做B。

【B数组就分为了 1   2    3    三个区域】

于是

那么我们的对调就还是分为两类。

1-2 2-3 1-3 直接一次性对调(need 1 ci per this gui)

和 1,2,3之间轮调(needs 2 ci per this gui)

【剩下的一类就是本来就在自己的区域上,并不需要调动】

所以Answer = x + y/3+2 (其中 x 表示用方式一 进行对调的 对数(注意是对数) , y 表示所有数中需要用方式2进行轮调的数字个数)

(又因为 每次对调可以解决3个数的问题 所以共y/3次轮调,但每次又花费次数为2,所以乘以2就是花费了)

 

代码:

#include <stdio.h>

int a[1001];

int compare(int s1,int e1,int num1,int s2,int e2,int num2){
    int i,j,sum=0;
    for(i=s1,j=s2;i<s1+e1 && j<s2+e2;i++,j++){
        if(a[i]==num2 || a[j]==num1){
            if(a[j]!=num1){
                for(;j<s2+e2;j++)
                    if(a[j]==num1)
                        break;
            }
            else if(a[i]!=num2){
                for(;i<s1+e1;i++)
                    if(a[i]==num2)
                        break;
            }
            if(i==s1+e1 || j==s2+e2)
                break;
            a[i]^=a[j];
            a[j]^=a[i];
            a[i]^=a[j];
            sum++;
        }
    }
    return sum;
}

void solve(int n){
    int i,sum=0,count=0;
    int num[3]={0};
    for(i=0;i<n;i++)
        num[a[i]-1]++;
    sum+=compare(0,num[0],1,num[0],num[1],2);
    sum+=compare(num[0],num[1],2,num[0]+num[1],num[2],3);
    sum+=compare(0,num[0],1,num[0]+num[1],num[2],3);
    for(i=0;i<num[0];i++){
        if(a[i]!=1)
            count++;
    }
 for(;i<num[0]+num[1];i++){
  if(a[i]!=2)
   count++;
 }
 for(;i<n;i++){
  if(a[i]!=3)
   count++;
 }
    sum+=count/3*2;
    printf(“%d\n”,sum);
}
int main(){
    int n;
    while(scanf(“%d”,&n)!=EOF){
        int i;
        for(i=0;i<n;i++)
            scanf(“%d”,&a[i]);
        solve(n);
    }
    return 0;
}

 

你可能感兴趣的:(Sorting a Three-Valued Sequence)