算法导论代码 第15章 动态规划

来源:互联网 发布:vm桥接模式 无网络 编辑:程序博客网 时间:2024/05/07 08:01

第15章 动态规划

15.1 装配线调度

#include <stdio.h>#include <stdlib.h>enum { NUM = 6 };void fastest_way(int n,int a[][n], int t[][n - 1], int e[], int x[], int f[][n], int l[][n], int *fastest_time, int *last_line){f[0][0] = e[0] + a[0][0];f[1][0] = e[1] + a[1][0];for (int j = 1; j < n; j++) {if (f[0][j - 1] <= f[1][j - 1] + t[1][j - 1]) {f[0][j] = f[0][j - 1] + a[0][j];l[0][j] = 0;} else {f[0][j] = f[1][j - 1] + t[1][j - 1] + a[0][j];l[0][j] = 1;}if (f[1][j - 1] <= f[0][j - 1] + t[0][j - 1]) {f[1][j] = f[1][j - 1] + a[1][j];l[1][j] = 1;} else {f[1][j] = f[0][j - 1] + t[0][j - 1] + a[1][j];l[1][j] = 0;}}if (f[0][NUM - 1] + x[0] <= f[1][n - 1] + x[1]) {*fastest_time = f[0][n - 1] + x[0];*last_line = 0;} else {*fastest_time = f[1][n - 1] + x[1];*last_line = 1;}}void print_stations(int n,int line[][n], int last_line){int i = last_line;printf("line %d, station %d\n", i + 1, n);for (int j = n - 1; j > 0; j--) {i = line[i][j];printf("line %d, station %d\n", i + 1, j);}}int main(){int n=NUM;int f[2][NUM];int l[2][NUM];int a[2][NUM] = { {7, 9, 3, 4, 8, 4}, {8, 5, 6, 4, 5, 7} };int t[2][NUM - 1] = { {2, 3, 1, 3, 4}, {2, 1, 2, 2, 1} };int e[2] = { 2, 4 };int x[2] = { 3, 2 };int fastest_time;int last_line;fastest_way(n,a, t, e, x, f, l, &fastest_time, &last_line);printf("%d %d\n", fastest_time, last_line + 1);printf("输出F数组:\n");for (int i = 0; i < n; ++i) {printf("%2d ", f[0][i]);}printf("\n");for (int i = 0; i < n; ++i) {printf("%2d ", f[1][i]);}printf("\n");printf("输出L数组:\n");for (int i = 1; i < n; ++i) {printf("%2d ", l[0][i] + 1);}printf("\n");for (int i = 1; i < n; ++i) {printf("%2d ", l[1][i] + 1);}printf("\n");print_stations(n,l, last_line);return 0;}


15.2 矩阵链相乘

15.2.1 矩阵相乘

#include <stdio.h>#include <stdlib.h>typedef struct matrix_type *matrix;struct matrix_type {int row;int col;int **data;};matrix matrix_create(int row, int col){if (row == 0)return NULL;matrix m = malloc(sizeof(struct matrix_type));m->row = row;m->col = col;m->data = malloc(sizeof(int *) * row);for (int i = 0; i < row; i++) {m->data[i] = malloc(sizeof(int) * col);for (int j = 0; j < col; j++) {m->data[i][j] = 0;}}return m;}void matrix_destroy(matrix m){for (int i = 0; i < m->row; i++)free(m->data[i]);free(m->data);free(m);}void matrix_display(matrix m){for (int i = 0; i < m->row; ++i) {for (int j = 0; j < m->col; ++j) {printf("%2d ", m->data[i][j]);}printf("\n");}}void matrix_multiply(matrix A, matrix B, matrix C){if (A->col != B->row) {return;}for (int i = 0; i < A->row; ++i) {for (int j = 0; j < B->col; ++j) {C->data[i][j] = 0;for (int k = 0; k < A->col; ++k) {C->data[i][j] += A->data[i][k] * B->data[k][j];}}}}void matrix_copy(matrix mdst, matrix msrc){if (mdst->row != msrc->row || mdst->col != msrc->col) {matrix_destroy(mdst);mdst->row = msrc->row;mdst->col = msrc->col;mdst->data = malloc(sizeof(int *) * mdst->row);for (int i = 0; i < mdst->row; i++) {mdst->data[i] = malloc(sizeof(int) * mdst->col);}}for (int i = 0; i < mdst->row; i++) {for (int j = 0; j < mdst->col; j++) {mdst->data[i][j] = msrc->data[i][j];}}}int main(){matrix A = matrix_create(2, 4);matrix B = matrix_create(4, 3);for (int i = 0; i < A->row; ++i) {for (int j = 0; j < A->col; ++j) {A->data[i][j] = 1;/*全部是1,为了测试方便随便设置的值 */}}printf("输出A矩阵的值:\n");matrix_display(A);for (int i = 0; i < B->row; ++i) {for (int j = 0; j < B->col; ++j) {B->data[i][j] = 2;/*全部是2,为了测试方便随便设置的值 */}}printf("输出B矩阵的值:\n");matrix_display(B);matrix C = matrix_create(A->row, B->col);matrix_multiply(A, B, C);printf("输出C矩阵的值:\n");matrix_display(C);matrix D = matrix_create(C->row, C->col);matrix_copy(D, C);printf("输出D矩阵的值:\n");matrix_display(D);matrix_destroy(A);matrix_destroy(B);matrix_destroy(C);matrix_destroy(D);return 0;}


15.2.2 求矩阵链的最优加全部括号

#include <stdio.h>#include <limits.h>#include <stdlib.h>enum { NUM = 7 };void matrix_chain_order(int n,int p[], int m[][n], int s[][n]){for (int i = 1; i < n; ++i) {m[i][i] = 0;}for (int l = 2; l < n; ++l) {for (int i = 1; i < n - l + 1; ++i) {int j = i + l - 1;m[i][j] = INT_MAX;for (int k = i; k <= j - 1; ++k) {int q =    m[i][k] + m[k + 1][j] + p[i -      1] * p[k] * p[j];if (q < m[i][j]) {m[i][j] = q;s[i][j] = k;}}}}}void print_optimal_matrix(int n,int s[][n], int i, int j){if (i == j) {printf("A%d", i);} else {printf("(");print_optimal_matrix(n,s, i, s[i][j]);print_optimal_matrix(n,s, s[i][j] + 1, j);printf(")");}}int main(){int n=NUM;int p[NUM] = { 30, 35, 15, 5, 10, 20, 25 };int m[NUM][NUM] = { {0} };int s[NUM][NUM] = { {0} };matrix_chain_order(n,p, m, s);printf("最优加全部括号\n");print_optimal_matrix(n,s, 1, 6);printf("\n");printf("输出m数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", m[i][j]);}printf("\n");}printf("输出s数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", s[i][j]);}printf("\n");}return 0;}


15.3 动态规划基础

15.3.1 递归求矩阵链的最优加全部括号

#include <stdio.h>#include <limits.h>#include <stdlib.h>enum { NUM = 7 };int recursive_matrix_chain(int n,int p[], int i, int j, int m[][n], int s[][n]){if (i == j) {return 0;}m[i][j] = INT_MAX;for (int k = i; k <= j - 1; k++) {int q = recursive_matrix_chain(n,p, i, k, m, s)    + recursive_matrix_chain(n,p, k + 1, j, m, s)    + p[i - 1] * p[k] * p[j];if (q < m[i][j]) {m[i][j] = q;s[i][j] = k;}}return m[i][j];}void print_optimal_matrix(int n,int s[][n], int i, int j){if (i == j) {printf("A%d", i);} else {printf("(");print_optimal_matrix(n,s, i, s[i][j]);print_optimal_matrix(n,s, s[i][j] + 1, j);printf(")");}}int main(){int n=NUM;int p[NUM] = { 30, 35, 15, 5, 10, 20, 25 };int m[NUM][NUM] = { {0} };int s[NUM][NUM] = { {0} };recursive_matrix_chain(n,p, 1, 6, m, s);printf("最优加全部括号\n");print_optimal_matrix(n,s, 1, 6);printf("\n");printf("输出m数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", m[i][j]);}printf("\n");}printf("输出s数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", s[i][j]);}printf("\n");}return 0;}


15.3.2 加了备忘的递归求矩阵链的最优加全部括号

#include <stdio.h>#include <limits.h>#include <stdlib.h>enum { NUM = 7 };int lookup_chain(int n, int p[], int i, int j, int m[][n], int s[][n]){if (m[i][j] < INT_MAX) {return m[i][j];}if (i == j) {m[i][j] = 0;} else {for (int k = i; k <= j - 1; ++k) {int q = lookup_chain(n, p, i, k, m, s)    + lookup_chain(n, p, k + 1, j, m, s)    + p[i - 1] * p[k] * p[j];if (q < m[i][j]) {m[i][j] = q;s[i][j] = k;}}}return m[i][j];}int memoized_matrix_chain(int n, int p[], int m[][n], int s[][n]){for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {m[i][j] = INT_MAX;}}return lookup_chain(n, p, 1, n - 1, m, s);}void print_optimal_matrix(int n, int s[][n], int i, int j){if (i == j) {printf("A%d", i);} else {printf("(");print_optimal_matrix(n, s, i, s[i][j]);print_optimal_matrix(n, s, s[i][j] + 1, j);printf(")");}}int main(){int n = NUM;int p[NUM] = { 30, 35, 15, 5, 10, 20, 25 };int m[NUM][NUM] = { {0} };int s[NUM][NUM] = { {0} };memoized_matrix_chain(n, p, m, s);printf("最优加全部括号\n");print_optimal_matrix(n, s, 1, 6);printf("\n");printf("输出m数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", m[i][j] == INT_MAX ? 0 : m[i][j]);}printf("\n");}printf("输出s数组的值\n");for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j) {printf("%5d ", s[i][j]);}printf("\n");}return 0;}


15.4 最长公共子串

15.4.1 求最长公共子串

#include <stdio.h>#include <string.h>#include <stdlib.h>enum direction_enum {direction_up,direction_left,direction_left_up};void lcs_length(char *X, char *Y, int m, int n, int c[][n], int b[][n]){for (int i = 0; i < m; ++i) {c[i][0] = 0;}for (int j = 0; j < n; ++j) {c[0][j] = 0;}for (int i = 1; i < m; ++i) {for (int j = 1; j < n; ++j) {if (X[i] == Y[j]) {c[i][j] = c[i - 1][j - 1] + 1;b[i][j] = direction_left_up;} else {if (c[i - 1][j] >= c[i][j - 1]) {c[i][j] = c[i - 1][j];b[i][j] = direction_up;} else {c[i][j] = c[i][j - 1];b[i][j] = direction_left;}}}}}void print_lcs(int n,char *X, int b[][n], int i, int j){if (i == 0 || j == 0)return;if (b[i][j] == direction_left_up) {print_lcs(n,X, b, i - 1, j - 1);printf("%c", X[i]);} else {if (b[i][j] == direction_up) {print_lcs(n,X, b, i - 1, j);} else {print_lcs(n,X, b, i, j - 1);}}}int main(){char X[] = "0ABCBDAB";//X,Y的有效字符的位置从1开始,前面的0是用来填充char Y[] = "0BDCABA";int m=strlen(X);int n=strlen(Y);int c[m][n];int b[m][n];lcs_length(X, Y, m, n, c, b);print_lcs(n,X, b, m-1, n-1);printf("\n");printf("输出C数组:\n");for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {printf("%d ", c[i][j]);}printf("\n");}return 0;}


15.4.2 求最长公共子串,不使用b数组

#include <stdio.h>#include <string.h>#include <stdlib.h>enum direction_enum {direction_up,direction_left,direction_left_up};void lcs_length(char *X, char *Y, int m, int n, int c[][n]){for (int i = 0; i < m; ++i) {c[i][0] = 0;}for (int j = 0; j < n; ++j) {c[0][j] = 0;}for (int i = 1; i < m; ++i) {for (int j = 1; j < n; ++j) {if (X[i] == Y[j]) {c[i][j] = c[i - 1][j - 1] + 1;} else {if (c[i - 1][j] >= c[i][j - 1]) {c[i][j] = c[i - 1][j];} else {c[i][j] = c[i][j - 1];}}}}}void print_lcs(int n,char *X, int c[][n], int i, int j){if (i == 0 || j == 0)return;if (c[i][j] == c[i - 1][j - 1] + 1) {print_lcs(n,X, c, i - 1, j - 1);printf("%c", X[i]);} else {if (c[i][j] == c[i - 1][j]) {print_lcs(n,X, c, i - 1, j);} else {print_lcs(n,X, c, i, j - 1);}}}int main(){char X[] = "0ABCBDAB";//X,Y的有效字符的位置从1开始,前面的0是用来填充char Y[] = "0BDCABA";int m=strlen(X);int n=strlen(Y);int c[m][n];lcs_length(X, Y, m, n, c);print_lcs(n,X, c, m-1, n-1);printf("\n");printf("输出C数组:\n");for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {printf("%d ", c[i][j]);}printf("\n");}return 0;}


15.4.3 求最长公共子串,X,Y字符串有效字符从0开始算

#include <stdio.h>#include <string.h>#include <stdlib.h>enum direction_enum {direction_up,direction_left,direction_left_up};void lcs_length(char *X, char *Y, int m, int n, int c[][n]){for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (X[i] == Y[j]) {if (i > 0 && j > 0) {c[i][j] = c[i - 1][j - 1] + 1;} else {c[i][j] = 1;}} else {int a = i > 0 ? c[i - 1][j] : 0;int b = j > 0 ? c[i][j - 1] : 0;if (a >= b) {c[i][j] = a;} else {c[i][j] = b;}}}}}void print_lcs(int n,char *X, int c[][n], int i, int j){if (i == 0 || j == 0)return;if (c[i][j] == c[i - 1][j - 1] + 1) {print_lcs(n,X, c, i - 1, j - 1);printf("%c", X[i]);} else {if (c[i][j] == c[i - 1][j]) {print_lcs(n,X, c, i - 1, j);} else {print_lcs(n,X, c, i, j - 1);}}}int main(){char X[] = "ABCBDAB";char Y[] = "BDCABA";int m=strlen(X);int n=strlen(Y);int c[m][n];lcs_length(X, Y, 7, 6, c);print_lcs(n,X, c, m-1, n-1);printf("\n");printf("输出C数组:\n");for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {printf("%d ", c[i][j]);}printf("\n");}return 0;}


15.5 最优二叉查找树

#include <stdio.h>#include <limits.h>#include <stdlib.h>void optimal_bst(float p[], float q[], int n, float e[][n], float w[][n], int root[][n]){for (int i = 1; i < n + 1; ++i) {e[i][i - 1] = q[i - 1];w[i][i - 1] = q[i - 1];}for (int l = 1; l < n; ++l) {for (int i = 1; i < n - l + 1; ++i) {int j = i + l - 1;e[i][j] = INT_MAX;w[i][j] = w[i][j - 1] + p[j] + q[j];for (int r = i; r <= j; ++r) {float t = e[i][r - 1] + e[r + 1][j] + w[i][j];if (t < e[i][j]) {e[i][j] = t;root[i][j] = r;}}}}}int main(){float p[] = { INT_MAX, 0.15, 0.10, 0.05, 0.10, 0.20 };//忽略第一个,INT_MAX是随便设置的值float q[] = { 0.05, 0.10, 0.05, 0.05, 0.05, 0.10 };int n=sizeof(p)/sizeof(p[0]);float e[n+1][n];float w[n+1][n];int root[n+1][n];optimal_bst(p, q, n, e, w, root);printf("输出e数组的值:\n");for (int i = 1; i < n+1; i++) {for (int j = 0; j < n; j++) {if (j == i - 1 || i <= j) {printf("%-4.2f ",e[i][j]);}}printf("\n");}printf("输出w数组的值:\n");for (int i = 1; i < n+1; i++) {for (int j = 0; j < n; j++) {if (j == i - 1 || i <= j) {printf("%-4.2f ",w[i][j]);}}printf("\n");}printf("输出root数组的值:\n");for (int i = 1; i < n+1; i++) {for (int j = 1; j < n; j++) {if (i <= j) {printf("%4d ",root[i][j]);}}printf("\n");}return 0;}


原创粉丝点击