题意:
随意给定一串数字1,2,3,求最少多少次交换操作可以将其按升序排列,输出最少次数以及每次交换的位置。
代码:
#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 ;
}