计数排序 简单贪心

题意:

    随意给定一串数字1,2,3,求最少多少次交换操作可以将其按升序排列,输出最少次数以及每次交换的位置。


代码:


#include<iostream>
#include<cstring>
using namespace std ;

int min(int a, int b){
    if(a>b) return b ;
    else return a ;
}
int main(){
    int n, i, j ;
    int a[1001], b[1001], s[4][4] ;
    cin >> n ;
    int num[4] ;
    int sum, key ;
    memset(num, 0, sizeof(num)) ;
    for(i=1; i<=n; i++){
        cin >> a[i] ;
        num[a[i]] ++ ;              //记录每个数的个数
    }
    for(i=1; i<=num[1]; i++)        //计数排序
        b[i] = 1 ;
    for(; i<=num[1]+num[2]; i++)
        b[i] = 2 ;
    for(; i<=n; i++)
        b[i] = 3 ;
    memset(s, 0, sizeof(s)) ;
    for(i=1; i<=n; i++)
        s[a[i]][b[i]] ++ ;
    sum = min(s[1][2], s[2][1]) + min(s[2][3], s[3][2]) + min(s[1][3], s[3][1]) ;//两两交换的最小次数
    sum += (n-s[1][1]-s[2][2]-s[3][3]-sum*2) / 3 * 2 ;      //所有交换实现的最小次数
    cout << sum << endl ;
    for(i=1; i<=n; i++){
        if(a[i]!=b[i]){
            for(j=i+1; j<=n; j++)
                if(a[j]==b[i]&&a[j]!=b[j]){
                    key = j ;
                    if(b[j]==a[i])   break ;    //若成立,则可同时实现两个位置的要求
                }
        cout << i << " " << key << endl ;      //key为同时实现两个位置要求的索引或b中最后一个a[j]的位置
        int t = a[i] ;          //实现交换
        a[i] = a[key] ;
        a[key] = t ;
        }
    }
    return 0 ;
}
原文地址:https://www.cnblogs.com/xiaolongchase/p/2137840.html