分析:首先咱們要知道調用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 }