冒泡排序的改编版本-动态规划
冒泡排序的移动次数等于数组中逆序对的个数。给定任一数组,它的逆序对总数一定是固定的。那么根据题意我们需要翻转一些连续数组,那么我们求出每次翻转数组逆序对改变最大的就是我们所要的结果。整个过程可以用动态规划的思想
dp[i][j]表示前i个数总共旋转j次最多能够减少的逆序数对
dp[i][j] = max(dp[i-1][j] , before[t][i]-after[t][i]+dp[t-1][j-1]) (0<=t<i)
before[t][i]表示下标t到i之间数组翻转前的逆序对个数
after[t][i]表示下标t到i之间数组翻转后的逆序对个数
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n=sc.nextInt(); int k=sc.nextInt(); int[] a=new int[n]; for(int i=0;i<n;i++) a[i]=sc.nextInt(); int[][]dp =new int[n+1][k+1];//表示前i个数总共旋转j次最多能够减少的逆序数对 for(int i=2;i<=n;i++) { for(int j=1;j<=k;j++) { int temp=Integer.MIN_VALUE; for(int t=i-1;t>=1;t--) { temp=Math.max(countReverseBefore(a,t-1,i-1)-countReverseAfter(a,t-1,i-1)+dp[t-1][j-1], temp); // System.out.println(countReverseAfter(a,t-1,i-1)); } dp[i][j]=Math.max(dp[i-1][j], temp); } } System.out.println(countReverseBefore(a,0,n-1)-dp[n][k]); } private static int countReverseBefore(int[] arr, int begin, int end) { int count = 0; for (int i = begin; i <= end; i++) { for (int j = i+1; j <= end; j++) { if (arr[j] < arr[i]) count++; } } return count; } private static int countReverseAfter(int[] arr, int begin, int end) { int count = 0; for (int i = end; i >= begin; i--) { for (int j = i-1; j >=begin; j--) { if (arr[j] < arr[i]) count++; } } return count; } }
本文来自博客园,作者:LeeJuly,转载请注明原文链接:https://www.cnblogs.com/peterleee/p/10885114.html

浙公网安备 33010602011771号