USACO 2.1.3 Sorting a Three-Valued Sequence 三值的排序

Problem C: 2.1.3 Sorting a Three-Valued Sequence 三值的排序

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 13  Solved: 9
[Submit][Status][Web Board]

Description

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

Input

Line 1: N (1 <= N <= 1000) Lines 2-N+1: 每行一个数字,共N行。(1..3)

Output

共一行,一个数字。表示排成升序所需的最少交换次数。

Sample Input

9
2
2
1
3
3
3
2
3
1

Sample Output

4

解题思想:

先检查1,能放回原位就放回,检查两遍保证1都放好,再检查2与3,还比较简单

二维数组a[][]按1 2 3的数量分开,第一行共有c1个位置...排好序后第一行全是1,第二行全是2... 

将1归位:遍历第一行将第一行为2且第二行为1,或者将第一行为3且第三行为1的交换,此时每交换1次有两个数归位

                   扫描第二、三行,使得二三行有1的,交换,使1归位,此时每交换1次只有1归位。

将2归位:剩下的就是将第二行的3与第三行的2交换,全部归位



#include <iostream>

using namespace std;

int a[1005][1005];
int b[1005];

int main()
{
    int i,j,k;
    int c1=0,c2=0,c3=0,ct=0,n;
    cin>>n;

    for(i=1;i<=n;i++)                              //统计1 2 3的个数,并把数存到b[]中
    {
        cin>>b[i];
        if(b[i]==1)
            c1++;
        if(b[i]==2)
            c2++;
        if(b[i]==3)
            c3++;
    }

    for(i=1;i<=c1;i++)                             //二维数组a[][]按1 2 3的数量分开,第一行共有c1个位置...排好序后第一行全是1,第二行全是2...
        a[1][i]=b[i];
    for(i=c1+1;i<=c1+c2;i++)
        a[2][i-c1]=b[i];
    for(i=c1+c2+1;i<=n;i++)
        a[3][i-c1-c2]=b[i];

    for(j=1;j<=c1;j++)                             //将1归位:遍历第一行将第一行为2且第二行为1,或者将第一行为3且第三行为1的交换,此时交换1次有两个数归位
    {                                              
        if(a[1][j]==2)
        {
            for(i=1;i<=c2;i++)
            {
                if(a[2][i]==1)
                {
                    b[0]=a[1][j];
                    a[1][j]=a[2][i];
                    a[2][i]=b[0];

                    ct++;
                    break;
                }
            }
        }

        if(a[1][j]==3)
        {
            for(i=1;i<=c3;i++)
            {
                if(a[3][i]==1)
                {
                    b[0]=a[1][j];
                    a[1][j]=a[3][i];
                    a[3][i]=b[0];

                    ct++;
                    break;
                }
            }
        }
    }

    for(i=1;i<=c2;i++)                                      //扫描第二、三行,使得二三行有一的,交换,使一归位,此时只有一归位。
    {                                                       //至此一全部归位,剩下的就是将第二行的3与第三行的2交换,全部归位
        if(a[2][i]==1)
        {
            for(j=1;j<=c1;j++)
            {
                if(a[1][j]!=1)
                {
                    b[0]=a[1][j];
                    a[1][j]=a[2][i];
                    a[2][i]=b[0];

                    ct++;
                    break;
                }
            }
        }
    }


    for(i=1;i<=c3;i++)
    {
        if(a[3][i]==1)
        {
            for(j=1;j<=c1;j++)
            {
                if(a[1][j]!=1)
                {
                    b[0]=a[1][j];
                    a[1][j]=a[3][i];
                    a[3][i]=b[0];

                    ct++;
                    break;
                }
            }
        }
    }

    for(i=1;i<=c2;i++)
    {
        if(a[2][i]==3)
        {
            for(j=1;j<=c3;j++)
            {
                if(a[3][j]==2)
                {
                    b[0]=a[3][j];
                    a[3][j]=a[2][i];
                    a[2][i]=b[0];

                    ct++;
                    break;
                }
            }
        }
    }
    
    cout<<ct<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值