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

第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;
}


你可能感兴趣的:(c,算法,struct,UP,float,Matrix)