FZoj 2166 inversion
题意:给一个整数序列a1,a2,a3…,an,其逆序数对数为满足 i<j
且 ai>aj
的(i,j)对数。交换两个数,使得逆序数对数最少
思路:交换任意两个位置(i,j)的数,只有i与j之间的数 才会对逆序数对数有影响,找出影响最大的(也就是让逆序数对减少最多的 )
dp1[i][j] 表示i和j之间的数和 i 比较 逆序数对数减少的数量,dp2[i][j]表示i和j之间的数和 j 比较 逆序数对数减少的数量,然后合并
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 5 using namespace std; 6 7 const int T=1e3+5; 8 9 int dp1[T][T],dp2[T][T],a[T],sum; 10 11 int find( int A, int B ) 12 { 13 if( A > B ) return 1; 14 if( A < B ) return -1; 15 return 0; 16 } 17 18 void begin( int n ) 19 { 20 sum=0; 21 for(int i=1;i<=n;i++) 22 for(int j=i+1;j<=n;j++) 23 if( a[i] > a[j] ) 24 sum++; 25 } 26 27 int main( ) 28 { 29 int n,Min,s; 30 while(~scanf("%d",&n)) 31 { 32 Min=0; 33 memset(dp1,0,sizeof(dp1)); 34 memset(dp2,0,sizeof(dp2)); 35 for(int i=1;i<=n;i++) 36 scanf("%d",&a[i]); 37 begin( n ); 38 for(int i=1;i<=n;i++) 39 for(int j=i+2;j<=n;j++) 40 dp1[i][j]=dp1[i][j-1]-find( a[i], a[j-1]); 41 for(int j=n;j>=1;j--) 42 for(int i=j-2;i>=1;i--) 43 dp2[i][j]=dp2[i+1][j]+find( a[j], a[i+1]); 44 for(int i=1;i<=n;i++) 45 for(int j=i+1;j<=n;j++) 46 dp1[i][j]+=dp2[i][j]-find( a[i], a[j]); 47 for(int i=1;i<=n;i++) 48 { 49 for(int j=i+1;j<=n;j++) 50 { 51 if( dp1[i][j] < Min) 52 Min=dp1[i][j]; 53 } 54 } 55 printf("%d\n",sum+Min); 56 } 57 return 0; 58 }