Sorting a Three-Valued Sequence (模拟)

Sorting a Three-Valued Sequence
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
 use MathJax to parse formulas

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但是三个数的顺序为2,3,1.这时候我们需要进行2次调换

                            才能让1,2,3在自己的位置上,也就是付出2次操作的代价换来了3个数字归位

                2.三个数中只有一个数在自己的位置上,例如位置为1,2,3,但是三个数字的顺序为3,2,1,。这时候我们需要调换1和3才能使三个数归位,也就是付出了1次操作的代价换来了2个相互调换位置的数归位

                 3.三个数都在自己位置上,这时候不需要进行操作


所以我们需要做的是:先找出情况2的次数(因为让两数归位不会影响情况1),然后找出情况1的次数

    

设c12为数组c中1区域中含有2的数目,则同理设出c21,c13,c31,c23,c32;

然后设cnt为没有在自己位置上的数字的数目;

则需要进行2操作的次数为:ans1 = min(cn12,cn21)+min(cn13,cn31)+min(cn23,cn32);

进行三操作的次数为:ans2 = (cnt - ans*2 )*2/3               ///进行2操作后剩下的次数乘以2/3即进行3操作的次数

所以答案为ans = ans2+ans1;

代码如下

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#define For(i,n) for(int i=0;i<n;i++)
#define mem(a) memset(a,0,sizeof(a))

using namespace std;
typedef long long ll;
const int maxn = 1e4+2;
ll a[maxn],b[maxn];
int main() {
    ll r1,r2;
    ll n,i;
    ll cnt;
    cin >> n;
    cnt = 0;
    mem(a);
    mem(b);
    For(i,n) {
        cin >> a[i];
        b[i] = a[i];
        }
    sort(b,b+n);
    for(i=1; i<n; i++) {
        if(b[i-1]==1&&b[i]==2)
            r1 = i;
        if(b[i-1]==2&&b[i]==3)
            r2 = i;
        }

    ll cn12,cn31,cn21,cn23,cn13,cn32;
    cn31 = cn21 = cn23 = cn12 = cn13=cn32=0;
    for(i=0; i<n; i++) {
        if(i>=r1&&i<r2) {
            if(a[i]==1)
                cn21++,cnt++;
            else if(a[i]==3)
                cn23++,cnt++;
            }
        else if(i>=r2) {
            if(a[i]==1)
                cn31++,cnt++;
            if(a[i]==2)
                cn32++,cnt++;
            }
        else {
            if(a[i]==2)
                cn12++,cnt++;
            if(a[i]==3)
                cn13++,cnt++;
            }
        }
    ll ans = min(cn12,cn21)+min(cn23,cn32)+min(cn13,cn31);
    ans += (cnt-ans*2)/3*2;
    cout << ans<<endl;

    return 0;
    }

posted @ 2018-04-02 16:18  秃头大师  阅读(133)  评论(0编辑  收藏  举报