一个关于矩阵的递归问题

来源:互联网 发布:2015国内旅游数据 编辑:程序博客网 时间:2024/06/06 20:50

先来看一下问题:

显然可以用递归来做。

方法一,递归建立子矩阵:

// ex.cpp : 定义控制台应用程序的入口点。//说明:本题目,考虑到n的取值可能会较大,那么使用二维数组来存储矩阵A并进行计算将会占用极大的内存//空间,因此我采用了动态分配内存的方式。经过测试,当n为8时依旧可以运行无误,n更大时则未进行测试//另外,本题目需要用到求n次方的计算,考虑到math.h头文件中的pow函数是以double型来计算的,进行//强制类型转换会有丢失数据的可能性,因此我按照自己的思路重新写了mypow函数。#include "stdafx.h"#include <iostream>//#include <cmath>     pow 函数可能会丢失数据,故重写求方函数using namespace std;//******************************************************************************************//函数名:mypow//函数参数:int numdown  底数    int numup  指数//函数返回值:numdown 的 numup 次方,一个整型数值//函数功能:求 numdown 的 numup 次方//备注:因为cmath头文件中已有的pow函数采用的是近似运算,可能会丢失数据,故此处重写求方函数//******************************************************************************************int mypow(int numdown, int numup){int num = 1;for(int i = 0; i < numup; i++)       //为节省空间此处使用迭代而不用递归num = num * numdown;return num;}//******************************************************************************************//函数名:recursion//函数参数:int *A  指针A指向的地址存储待求值的矩阵A    int n  2的n次方为矩阵的阶数//函数返回值:矩阵运算后的结果,一个整型数值//函数功能:求矩阵A按题目要求的运算得出的结果//备注:使用递归的方法实现//******************************************************************************************int recursion(int *A ,int n){//当n为0时,直接返回该元素的值if( n == 0 )return A[0];//当n>0时,进行如下处理//首先申请子矩阵的内存空间int *A11 = new int [mypow(2, n-1) * mypow(2, n-1)];int *A12 = new int [mypow(2, n-1) * mypow(2, n-1)];int *A21 = new int [mypow(2, n-1) * mypow(2, n-1)];int *A22 = new int [mypow(2, n-1) * mypow(2, n-1)];//将原矩阵分块存储在子矩阵中for(int i = 0; i < mypow(2, n-1); i++)for(int j = 0; j < mypow(2, n-1); j++){A11[i * mypow(2, n-1) + j]=A[i * mypow(2, n) + j];A12[i * mypow(2, n-1) + j]=A[i * mypow(2, n) + j + mypow(2, n - 1)];A21[i * mypow(2, n-1) + j]=A[(i + mypow(2, n - 1))* mypow(2, n) + j];A22[i * mypow(2, n-1) + j]=A[(i + mypow(2, n - 1)) * mypow(2, n) + j + mypow(2, n - 1)];}//递归调用,进行计算。先存储在变量final中,以便后续进行释放内存空间int final = recursion(A11, n-1) * recursion(A22, n-1) - recursion(A12, n-1) * recursion(A21, n-1);//释放子矩阵的内存空间delete []A11;delete []A12;delete []A21;delete []A22;//返回结果return final;}int _tmain(int argc, _TCHAR* argv[]){while(true){//创建变量n以计算矩阵的阶数int n;cin >> n;//n为负数判错if(n < 0){cout << "n必须非负,请重新输入"<<endl;continue;}//求出矩阵的阶数并存储在变量n0中int n0 = mypow(2 ,n);//为矩阵A申请相应的内存空间int *A = new int [n0 * n0];//将待计算的矩阵A输入for(int i = 0; i < n0 * n0; i++)cin >> A[i];//进行运算并输出结果cout << recursion(A , n) << endl << endl;//释放内存空间delete []A;}system("pause");return 0;}

可以看出,上面的方法虽然使用了动态内存,然而每递归一次都会新申请一块内存空间来存储子矩阵,产生了很大的空间浪费,因此优化为下面的方法:

方法二,递归分块矩阵:

// ex.cpp : 定义控制台应用程序的入口点。// 这次懒,没有重写pow,直接用的math.h里的// 使用了随机数,同样最高对n=8进行了测试。只是生成随机数将会消耗很多时间#include "stdafx.h"#include <ctime>#include <cmath>#include <iostream>#include <cstdlib>using namespace std;//******************************************************************************************//函数名:recursion//函数参数:int *A  指针A指向的地址存储待求值的矩阵A    int col1,col2,row1,row2    //         待计算矩阵的起始列、行和终止列、行            int n  n为矩阵的阶数//函数返回值:矩阵运算后的结果,一个整型数值//函数功能:求矩阵A按题目要求的运算得出的结果//备注:使用递归的方法实现//******************************************************************************************int recursion(int *A, int col1, int col2, int row1, int row2, int n){if (col1 == col2)return A[row1*n + col1];return recursion(A, col1, (col1 + col2) / 2, row1, (row1 + row2) / 2, n) *recursion(A, (col1 + col2) / 2 + 1, col2, (row1 + row2) / 2 + 1, row2, n) -recursion(A, (col1 + col2) / 2 + 1, col2, row1, (row1 + row2) / 2, n) *recursion(A, col1, (col1 + col2) / 2, (row1 + row2) / 2 + 1, row2, n);}int _tmain(int argc, _TCHAR* argv[]){while (true){//创建变量n以计算矩阵的阶数int n;cin >> n;//n为负数判错if (n < 0){cout << "n必须非负,请重新输入" << endl;continue;}//求出矩阵的阶数并存储在变量n0中int n0 = pow(2.0, n);//为矩阵A申请相应的内存空间int *A = new int[n0 * n0];//将待计算的矩阵A输入for (int i = 0; i < n0 * n0; i++)A[i] = (int)rand();//输出当前矩阵for (int i = 0; i < n0 * n0; i++){cout << A[i] << " ";if ((i + 1) % ((int)pow(2.0, n)) == 0)cout << '\n';}//进行运算并输出结果cout << recursion(A, 0, n0 - 1, 0, n0 - 1, n0) << endl << endl;//释放内存空间delete[]A;}system("pause");return 0;}

以上就是我的思路。恳请大佬批评指正! 


0 0