矩阵连乘问题算法思想_算法设计与分析-矩阵连乘问题

一、实验环境

操作系统:Windows 10 64位

内存:8GB

CPU:i5-5200U 2.20~2.20GHz

IDE:Code::Blocks 17.12

二、实验内容

1) 对于矩阵连乘问题,用递归程序穷举输出所有可能的加括号结果;

2) 对1)确定导致宕机的矩阵个数n的临界值;

3) 根据1)找出最优解,并把加括号的结果输出;

4) 对于矩阵连乘问题,用动态规划求最优解,并把加括号的结果输出;

三、代码实现

1) 版本1:用递归方法,穷举并对比找出最优解:

在main函数中的调用方法:

// 定义新类型typedef pair mul;

// 辅助函数bool Cmp(const mul m1, const mul m2);

vector combine(vector v1, vector v2, int left_d, int mid_d, int right_d);

vector allComb(int *dimensions, int left, int right);

void allPrint(vector allResult);

// 测试用的数据int n1 = 4, dimensions1[] = {50, 10, 40, 30, 5};

int n2 = 5, dimensions2[] = {50, 10, 40, 30, 5, 35};

int n3 = 6, dimensions3[] = {30, 35, 15, 5, 10, 20, 25};

int main()

{

int n = n1;

int *dimensions = dimensions1;

// 递归输出所有可能结果 vector allResult = allComb(dimensions, 1, n);

allPrint(allResult);

return 0;

}

allComb(找出所有加括号的结果)实现:

vector allComb(int *dimensions, int left, int right) {

vector comb;

if (left == right) comb.push_back(make_pair(to_string(left), 0));

vector sub1, sub2, temp;

for (int i = left; i < right; i++) {

sub1 = allComb(dimensions, left, i);

sub2 = allComb(dimensions, i + 1, right);

temp = combine(sub1, sub2, dimensions[left - 1], dimensions[i], dimensions[right]);

comb.insert(comb.begin(), temp.begin(), temp.end());

// allPrint(comb);

}

return comb;

}

辅助函数combine(用于整合子问题的结果)实现:

vector combine(vector v1, vector v2, int left_d, int mid_d, int right_d) {

vector result;

int s1 = v1.size(), s2 = v2.size(), temp_comp;

string temp;

for (int i = 0; i < s1; i++) {

for (int j = 0; j < s2; j++) {

temp = "(" + v1[i].first + v2[j].first + ")";

temp_comp = v1[i].second + v2[j].second + left_d * mid_d * right_d;

result.push_back(make_pair(temp, temp_comp));

}

}

return result;

}

辅助函数allPrint(用于输出所有加括号的结果以及最优解)实现:

void allPrint(vector allResult) {

sort(allResult.begin(), allResult.end(), Cmp);

int length = allResult.size();

cout << "Total: " << length << endl;

int prox = allResult[0].second, index = 0;

for (int i = 0; i < length; i++) {

if (allResult[i].second < prox) {

prox = allResult[i].second;

index = i;

}

cout << allResult[i].first << endl;

}

cout << endl << "Recursive method's result";

cout << endl << "The proximal solution costs "

<< prox << " times of multiplication. As shown below: " << endl;

cout << allResult[index].first << endl;

}

辅助函数Cmp(自定义排序方式)实现:

bool Cmp(const mul m1, const mul m2) {

return m1.first < m2.first;

}

2) 版本2:用动态规划找出最优解:

用到的辅助变量与函数如下:

// 动态规划求解

const int Max = 100;

int complexity[Max][Max], prox[Max][Max];

void proxComb(int *dimensions, int n, int complexity[][Max], int prox[][Max]);

void proxPrint(int n, int complexity[][Max], int prox[][Max]);

string proxString(int prox[][Max], int left, int right);

proxComb(找出最优的加括号结果)实现:

void proxComb(int *dimensions, int n, int complexity[][Max], int prox[][Max]) {

// complexity为记录乘法次数的矩阵,只用到上三角区域

// 对角线上的元素表示单个矩阵,故而乘法次数为0

for (int i = 1; i <= n; i++) complexity[i][i] = 0;

// 外循环为列,内循环从下往上更新complexity

for (int i = 2; i <= n; i++) {

for (int j = i - 1; j > 0; j--) {

// 初始化为从左数第一项

complexity[j][i] = 0 + complexity[j + 1][i] +

dimensions[j - 1] * dimensions[j] * dimensions[i];

prox[j][i] = j;

// 从左往右寻找更优的组合(如果有)

for (int k = j + 1; k < i; k++) {

int temp = complexity[j][k] + complexity[k + 1][i] +

dimensions[j - 1] * dimensions[k] * dimensions[i];

if (temp < complexity[j][i]) {

complexity[j][i] = temp;

prox[j][i] = k;

}

}

}

}

}

辅助函数proxPrint(用于输出最优解)实现:

void proxPrint(int n, int complexity[][Max], int prox[][Max]) {

string result = proxString(prox, 1, n);

cout << endl << "Dynamic programming's result";

cout << endl << "The proximal solution costs "

<< complexity[1][n] << " times of multiplication. As shown below: " << endl;

cout << result << endl;

}

辅助函数proxString(递归输出最优解的字符串)实现:

string proxString(int prox[][Max], int left, int right) {

if (left == right) {

return to_string(left);

}

int prox_point = prox[left][right];

string sub1 = proxString(prox, left, prox_point);

string sub2 = proxString(prox, prox_point + 1, right);

return "(" + sub1 + sub2 + ")";

}

四、代码测试/实验结果

1) 版本1:

n = 4时:

n = 6时:(部分截图)

n = 15时:(将输出结果的代码注释掉、以及不传入实际矩阵大小,只考虑矩阵个数)

而到了n = 20时,内存占用大致为85%~95%,应该是可以算出结果来的。但是等了45分钟后还没出结果,所以强制退出了。

而根据问题规模随n的增长速度来看,估计21~25的时候在本机配置下就会成功死机了。。。

2) 版本2:作为比较,使用两个版本的结果相互检验

n = 4时:

n = 6时:

The END.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值