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
",sum+Min);
56     }
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/lysr--tlp/p/3690888.html