Crazy Rows
给定一个由0和1组成的矩阵。只允许交换相邻的两行(第i i i 行和第i + 1 i+1 i + 1 行),要把矩阵化成下三角矩阵(主对角线上方的元素都是0),最少需要交换几次?输入的矩阵保证总能化成下三角矩阵。
输入
输出
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); }
Bribe the Prisoners
输入
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 ]); }