10-排序6 Sort with Swap(0, i)   (25分)

来源:互联网 发布:网络教育本科费用 编辑:程序博客网 时间:2024/06/03 21:23

Given any permutation of the numbers {0, 1, 2,...,N-1}, it is easy to sort them in increasing order. But what ifSwap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the following way:

Swap(0, 1) => {4, 1, 2, 0, 3}Swap(0, 3) => {4, 1, 2, 3, 0}Swap(0, 4) => {0, 1, 2, 3, 4}

Now you are asked to find the minimum number of swaps need to sort the given permutation of the firstNN nonnegative integers.

Input Specification:

Each input file contains one test case, which gives a positiveNN (10^5) followed by a permutation sequence of {0, 1, ..., N−1N-1}. All the numbers in a line are separated by a space.

Output Specification:

For each case, simply print in a line the minimum number of swaps need to sort the given permutation.

Sample Input:

103 5 7 2 6 4 9 0 8 1

Sample Output:

9


解析:

1、交换的次数最小,那么每次交换都应该把一个数换到它最终应该在的位置(这里把这个数叫做最终数)。

2、0如果在0号位,那么0必须换到一个位置(这个位置上的数不是最终数),这种情况会增加一次无用的交换,但这个交换也是必须的。

3、0不在0号位,那么要把0所在位置的最终数换到这个位置。

4、情况2需要找到0将要换到的位置,这里用set来存储这些位置(如果用遍历数组的方法来找,会超时)

5、情况3需要找到最终数所在的位置,这里使用mapA,即A数组的映射,来快速找到这个位置(用遍历数组的方法,同样会超时)

#include <cstdio>#include <cstdlib>#include <set>using namespace std;int A[100000], mapA[100000], N;set<int> s;void swap( int *a, int *b ) {int tmp = *a;*a = *b;*b = tmp;}int main () {int pos_zero, val_sub, pos_sub, cnt = 0;scanf("%d", &N);for ( int i = 0; i < N; i++ ) {scanf("%d", &A[i]);mapA[A[i]] = i;//记录映射if ( A[i] != i && i != 0 )  //保存会被交换位置,0不保存(因为0会被多次交换)s.insert(i);if ( A[i] == 0 )pos_zero = i;}while ( !s.empty() ) {if ( pos_zero != 0 ) {   //如果0不在自己的位置上val_sub = mapA[pos_zero];mapA[ A[pos_zero] ] = val_sub;//更新映射mapA[ A[val_sub] ] = pos_zero;swap( &A[pos_zero], &A[val_sub] );cnt++;s.erase(pos_zero);//pos_zero上的元素已确定,不会再被交换pos_zero = val_sub;//更新0的位置}else {if ( s.empty() )break;pos_sub = *s.begin();mapA[ A[pos_zero] ] = pos_sub;mapA[ A[pos_sub] ] = pos_zero;swap( &A[pos_zero], &A[pos_sub] );cnt++;pos_zero = pos_sub;}}printf("%d", cnt);system("pause");return 0;}