分析:首先咱们要知道调用swap()函数的次数跟什么有关。能够观察发如今Insertion Sort里,当且仅当a[j](j∈[0,i)) > a[i]时会调用一次swap(),也就是说有多少个a[j](j∈[0,i)) > a[i]成立就会调用多少次swap()(由于a[i]前面的序列都是有序的),这个数目也叫逆序数。因此要使调用swap()的次数最少,就应该要使整个序列的总的逆序数最小。这时,咱们能够枚举全部不一样的两个位置对换以后的总逆序数来找最小的总逆序数。但枚举的时候咱们须要知道a[i]与a[j]对换以后各自的逆序数以及对换以前的逆序数,记为b[i][j]、b[j][i]、b[i][i]、b[j][j]。由于咱们对换a[i]和a[j]的行为只会影响到i~j上的元素的逆序数,咱们能够用b[i][j]、b[j][i]、b[i][i]、b[j][j]推导出对换以后的总逆序数的增量。只要求出这个最小的增量咱们就能够求得最小的总逆序数。ios
那如今的关键就是比较快的求出数组b的全部元素的值。这个能够在O(n^2)的时间内完成。在n <= 5000的条件下应该仍是能够接受的。数组
这道题花了很多时间,主要缘由在于没把推导的公式写得清清楚楚,虽然知道推导公式的方法,可是没有很快的推出正确的公式。函数
1 #include <iostream> 2 #include <queue> 3 #include <string> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdio> 7 #include <map> 8 #include <vector> 9 using namespace std; 10 int a[5000], b[5000][5000], n; 11 int main(){ 12 cin >> n; 13 for (int i = 0; i < n; i++){ 14 cin >> a[i]; 15 } 16 for (int i = 0; i < n; i++){ 17 for (int j = 0; j < n; j++){ 18 b[i][j] = -1; 19 } 20 } 21 for (int i = 0; i < n; i++){ 22 b[i][0] = 0; 23 for (int j = 0; j < i; j++){ 24 if (a[i] < a[j]){ 25 b[i][j + 1] = b[i][j] + 1; 26 }else{ 27 b[i][j + 1] = b[i][j]; 28 } 29 } 30 for(int j = i + 1;j < n;j++){ 31 if(a[i] < a[j]){ 32 b[i][j] = b[i][j - 1] + 1; 33 }else{ 34 b[i][j] = b[i][j - 1]; 35 } 36 } 37 } 38 int ans = 0; 39 map<int,int> m; 40 for (int i = 0; i < n; i++){ 41 for (int j = i + 1; j < n; j++){ 42 int x = 2 * (b[i][j] - b[i][i] + b[j][i] - b[j][j]) - (a[i] < a[j]?1:0) + (a[i] > a[j]?1:0); 43 m[x]++; 44 ans = min(ans,x); 45 } 46 } 47 int counter = 0; 48 for (int i = 1; i < n; i++){ 49 int j = i; 50 while (j > 0 && a[j] < a[j - 1]) 51 { 52 swap(a[j], a[j - 1]); // swap elements a[j] and a[j - 1] 53 counter++; 54 j = j - 1; 55 } 56 } 57 cout << counter + ans << " " << m[ans] << endl; 58 return 0; 59 }