给定一个由0和1组成的矩阵。只允许交换相邻的两行(第i i i i + 1 i+1 i + 1 
1 2(交换第1行和第2行,再交换第2行和第3行,得到下三角矩阵) 
思路:
暂且先考虑一下最后应该把哪一行交换到第一行。最后的第一行应该具有00…0或是10…0的形式。可以交换到第1行的行当然也可以换到第2行及之后的行,当有多个满足条件的行时,选择距离第1行近的行对应的最终费用要小。对于之后的行就可以以同样的思路处理。
在这道题中,每行的0和1的位置并不重要,只要知道每行最后一个1所在的位置就足够了。如果先将这些位置预先计算好,那么就能降低行交换时的复杂度。直接按矩阵的形式处理的复杂度是O ( N 3 ) O(N^3) O ( N 3 ) O ( N 2 ) O(N^2) O ( N 2 ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 int  N;int  M[MAX_N][MAX_N];    int  a[MAX_N];       void  solve ()      int  res = 0 ;     for (int  i = 0 ; i < N; i++) {         int  pos = -1 ;           for (int  j = i; j < N; j++) {             if (a[j] <= i) {                 pos = j;                 break ;             }         }                  for (int  j = pos; j > i; j++) {             swap(a[j], a[j - 1 ]);             res++;         }     }     printf ("%d\n" , res); } 
1 P = 20,	 Q = 3, A = {3, 6, 14} 
1 35(按照14,6,3的熟悉怒释放,则需要19+12+4=35枚金币,是最少的) 
思路:动态规划
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const  int  MAX_Q = 20 ;int  P, Q, A[MAX_Q + 2 ];int  dp[MAX_Q + 1 ][MAX_Q + 2 ];void  solve ()           A[0 ] = 0 ;     A[Q + 1 ] = P + 1 ;          for (int  q = 0 ; q <= Q; q++) {         dp[q][q + 1 ] = 0 ;     }          for (int  w = 2 ; w <= Q + 1 ; w++) {         for (int  i = 0 ; i + w <= Q + 1 ; i++) {                          int  j = i + w, t = INT_MAX;                          for (int  k = i + 1 ; k < j; k++) {                 t = min(t, dp[i][k] + dp[k][j]);             }                          dp[i][j] = t + A[j] - A[i] - 2 ;         }     }     printf ("%d\n" , dp[0 ][Q + 1 ]); }