usaco: Sorting a Three-Valued Sequence

把原序列按 non-decreasing排序,然后把排序后的数组和原序列一一比较,找出本该排1的位置放了2的、3的,本该放2的位置放了1的、3的……

由于一次exchange可以把1和2对换,1和3对换,2和3对换,所以做这些交换,然后剩下的就是三个都不同的了,这样每一组都至少经过两次交换才能恢复(比如312经两次交换才可以变成123)。看代码更清楚,很简单的思路,很简短的代码。

/*
ID: 
LANG: C++
TASK: sort3
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int toChange[4][4];        //toChange[i][j]:本该排i的位置排了j
int N;
int num[1005];             //原数组
int sorted[1005];          //排序后的数组
int change;                //交换次数
int main()
{
    freopen("sort3.in", "rb", stdin);
    freopen("sort3.out", "wb", stdout);
    cin >> N;
    for(int i = 0; i < N; i++) {
        cin >> num[i];
        sorted[i] = num[i];
    }
    
    sort(sorted, sorted + N);
    
    memset(toChange, 0, sizeof(int));
    
    for(int i = 0; i < N; i++) {
        if(sorted[i] == 1 && num[i] == 2)
            toChange[1][2]++;
        else if(sorted[i] == 1 && num[i] == 3)
            toChange[1][3]++;
        else if(sorted[i] == 2 && num[i] == 1)
            toChange[2][1]++;
        else if(sorted[i] == 2 && num[i] == 3)
            toChange[2][3]++;
        else if(sorted[i] == 3 && num[i] == 1)
            toChange[3][1]++;
        else if(sorted[i] == 3 && num[i] == 2)
            toChange[3][2]++;
    }
    
    change = 0;
    int leave = 0;            //leave:两两交换之后剩下的
    for(int i = 1; i <= 2; i++) {
        for(int j = 1; j <= 3 - i; j++) {
            int minn = min(toChange[i][i+j], toChange[i+j][i]);
            change += minn;
            toChange[i][j+i] -= minn;
            toChange[j+i][i] -= minn;
            leave = leave + toChange[i][j+i] + toChange[j+i][i];
        }
    }
    
    change += leave * 2 / 3;
    
    cout << change << endl;
    
    fclose(stdin);
    fclose(stdout);
    return 0;
}
   


你可能感兴趣的:(c,Exchange,sorting)