确定结合律使用顺序以达到最小乘法次数
复杂度 O ( 2 n ) O(2^n) O(2n),由递推方程通过数学归纳法可证
#include
#include
using namespace std;
typedef vector<vector<int>> Matrix;
class Solution{
public:
int recurMatrixChain(vector<int> &P, int lo, int hi){
if (lo >= hi-1) return 0;
int res = INT_MAX;
for(int mid = lo+1; mid < hi; mid++){
int tmp = recurMatrixChain(P, lo, mid)+recurMatrixChain(P, mid, hi)+P[lo]*P[mid]*P[hi];
res = tmp < res ? tmp : res;
}
return res;
}
};
int main(int argc, const char * argv[]) {
unsigned seed = time(0);
srand(seed);
vector<int> p;
int n = 4;
for (int i = 0; i < n; i++){
p.push_back((rand()%100)+1);
}
for (int i : p){
cout << i << ',';
}
cout << endl;
Solution s;
cout << s.recurMatrixChain(p, 0, n-1) << endl;
return 0;
}
建立备忘录 O ( n 3 ) O(n^3) O(n3),通过标记函数获得最终括弧添加位置 O ( n ) O(n) O(n)
#include
#include
#include
#include
#include
#include
using namespace std;
typedef vector<vector<int>> Matrix;
class Solution{
private:
struct TreeNode{
string val;
TreeNode *lc, *rc;
};
vector<vector<int>> memo, mark; //备忘录与标记函数,标记函数在某些dp问题中不必需
TreeNode* root;
public:
//主算法
int iterateMatrixChain(vector<int> &p){
int n = p.size();
memo = vector<vector<int>> (n-1, *new vector<int>(n-1, 0));
mark = vector<vector<int>> (n-1, *new vector<int>(n-1, 0));
for (int numberOfMatrices = 2; numberOfMatrices < n; numberOfMatrices++){
for (int lo = 0; lo < n-numberOfMatrices; lo++){
int hi = lo+numberOfMatrices-1;
int least = INT_MAX;
for (int endOfFirst = lo; endOfFirst < hi; endOfFirst++){
int startOfSecond = endOfFirst+1;
int tmp = memo[lo][endOfFirst] + memo[startOfSecond][hi] + p[lo]*p[startOfSecond]*p[hi+1];
if (tmp < least){
least = tmp;
memo[lo][hi] = tmp;
mark[lo][hi] = endOfFirst;
}
}
}
}
root = establish(mark, 0, n-2);
return memo[0][n-2];
}
//建立表达式树
TreeNode* establish(vector<vector<int>> &mark, int lo, int hi){
TreeNode* cur = new TreeNode();
if (lo == hi){
cur->val = to_string(lo);
}else{
cur->val = ".";
int mid = mark[lo][hi];
cur->lc = establish(mark, lo, mid);
cur->rc = establish(mark, mid+1, hi);
}
return cur;
}
//扁平化,以将括弧插入字符串
list<string> inorder(TreeNode* cur){
list<string> l;
if (cur->val.compare(".") != 0){
l.push_back("A_{");
l.push_back(cur->val);
l.push_back("}");
}else{
l.push_back("(");
l.splice(l.end(), inorder(cur->lc));
l.splice(l.end(), inorder(cur->rc));
l.push_back(")");
}
return l;
}
//对外提供调用接口
list<string> getSequence(){
return inorder(root);
}
};
//main(int argc, const char * argv[])测试程序中涉及文件io
int main(int argc, const char * argv[]) {
vector<int> p = {30,35,15,5,10,20};
Solution s;
s.iterateMatrixChain(p);
list<string> l = s.getSequence();
string format1 = R"(\documentclass[10pt]{article}
\usepackage[usenames]{color} %used for font color
\usepackage{amssymb} %maths
\usepackage{amsmath} %maths
\usepackage[utf8]{inputenc} %useful to type directly diacritic characters
\begin{document}
\begin{align*})";
string format2 = R"(\end{align*}
\end{document})";
ofstream fs;
fs.open("yourOwnWorkspace/matrix.tex", ios::out);
fs << format1;
for (auto i : l){
fs << i;
}
fs << format2;
fs.close();
fs.open("yourOwnWorkspace/openlatex.sh", ios::out);
fs << R"(cd yourOwnWorkspace)" << endl;
fs << R"(latex ./matrix.tex)" << endl;
fs << R"(dvipdf ./matrix.dvi)" << endl;
fs.close();
chmod("yourOwnWorkspace/openlatex.sh", S_IEXEC);
system("yourOwnWorkspace/openlatex.sh");
return 0;
}
在源代码文件夹打开终端,使用
g++ -std=c++17 main.cpp -o main.out
,生成可执行文件
sudo ./main.out
,输入本机密码后,可执行文件获得sh执行权限,sh启动自动化脚本生成pdf文件。
pdf文件中矩阵运算次序指示:
时间复杂度上限 O ( n × m 2 ) O(n \times m^2) O(n×m2)
三层遍历处,最外层对列遍历有 n − 1 n-1 n−1次循环,内层等差数列求和,有 ( 1 + m ) m 2 \frac{(1+m)m}{2} 2(1+m)m次比较,乘法原理计数,共计 ( n − 1 ) ( 1 + m ) m 2 ≤ c ( n × m 2 ) , c \frac{(n-1)(1+m)m}{2} \le c(n \times m^2),c 2(n−1)(1+m)m≤c(n×m2),c为某一常数
#include
#include
#include
using namespace std;
class Matrix{
private:
vector<vector<int>> val;
public:
Matrix(int m, int n){
val = *new vector<vector<int>>(m, *new vector<int>(n, 0));
}
Matrix(vector<vector<int>> val){
this->val = val;
}
pair<int, int> getSize(){
return pair(val.size(), val[0].size());
}
int& operator()(int m, int n){ //not safe but doesn't matter
return val[m][n];
}
};
class Solution{
private:
Matrix profits; // [invest][project]
Matrix invests;
int maxProfit = 0;
int money = 0;
public:
Solution(Matrix profits):profits(profits),
invests(profits.getSize().first,
profits.getSize().second){
money = profits.getSize().first-1;
}
void findMaxProfit(){
pair<int, int> size = profits.getSize();
Matrix plans = *new Matrix(size.first, size.second);
for (int i = 0; i < size.first; i++){
plans(i, 0) = profits(i, 0);
invests(i, 0) = i;
}
for (int i = 1; i < size.second; i++){ //traverse projects
for (int j = 0; j < size.first; j++){ //traverse invests for first i projects
for (int k = 0; k <= j; k++){ //traverse invest for project i
if (plans(j-k, i-1)+profits(k, i) > plans(j, i)){
plans(j, i) = plans(j-k, i-1)+profits(k, i);
invests(j, i) = k;
}
}
}
}
// for test
cout << "备忘录:" << endl;
for (int i = 1; i < size.first; i++){
for (int j = 0; j < size.second; j++){
cout << plans(i, j) << "," << invests(i, j) << "\t";
}
cout << endl;
}
for (int i = 0; i < size.first; i++){
if (plans(i, size.second-1) > maxProfit){
maxProfit = plans(i, size.second-1);
}
}
}
int getMaxProfit(){
return maxProfit;
}
vector<int> getPlan(){
stack<int> s;
int money = this->money;
for (int i = invests.getSize().second-1; i >= 0; i--){
s.push(invests(money, i));
money -= invests(money, i);
}
vector<int> res;
while(!s.empty()){
res.push_back(s.top());
s.pop();
}
return res;
}
};
int main(int argc, const char * argv[]) {
//课件示例
vector<vector<int>> p = {{0,0,0,0},
{11,0,2,20},
{12,5,10,21},
{13,10,30,22},
{14,15,32,23},
{15,20,40,24}};
Matrix m(p);
Solution s(m);
s.findMaxProfit();
vector<int> plan = s.getPlan();
cout << "投资序列:" << endl;
for (auto i : plan){
cout << i << ",";
}
cout << endl;
cout << "总收益:" << endl;
cout << s.getMaxProfit() << endl;
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;
class Matrix{ //辅助类
public:
vector<vector<int>> val;
Matrix(unsigned long m, unsigned long n){
val = *new vector<vector<int>>(m, *new vector<int>(n, 0));
}
Matrix(vector<vector<int>> val){
this->val = val;
}
pair<int, int> getSize(){
return pair(val.size(), val[0].size());
}
int& operator()(int m, int n){
return val[m][n];
}
};
class Knapsack{
private:
unsigned long kinds;
unsigned long capacity;
vector<int> values;
vector<int> weights;
int maxValue;
Matrix plans;
public:
Knapsack(int capacity, vector<int>values, vector<int>weights):
plans(values.size(), capacity+1){
this->capacity = capacity;
this->values = values;
this->weights = weights;
kinds = values.size();
}
void pack(){
Matrix memo = Matrix(kinds, capacity+1);
for (unsigned long i = 0; i*weights[0] <= capacity; i++){
for (unsigned long j = 0; j < weights[0]; j++){
memo(0, i*weights[0]+j) = i*values[0];
plans(0, i*weights[0]+j) = i;
}
}
for (unsigned long i = 1; i < kinds; i++){
for (unsigned long j = 0; j <= capacity; j++){
for(int numberOfI = 0; numberOfI*weights[i] <= j; numberOfI++){
if (numberOfI*values[i]+memo(i-1, j-numberOfI*weights[i]) > memo(i, j)){
memo(i, j) = numberOfI*values[i]+memo(i-1, j-numberOfI*weights[i]);
plans(i, j) = numberOfI;
}
}
}
}
// 输出备忘录
for (int i = 0; i < kinds; i++){
for (int j = 1; j <= capacity; j++){
cout << memo(i, j) << "\t";
}
cout << endl;
}
maxValue = memo(kinds-1, capacity);
}
unsigned getMaxValue(){
return maxValue;
}
vector<int> getPlan(){
vector<int> plan;
stack<int> s;
int remain = capacity;
for (int i = kinds-1; i >= 0; i--){
s.push(plans(i, remain));
remain -= (s.top())*weights[i];
}
while(s.size()){
plan.push_back(s.top());
s.pop();
}
return plan;
}
};
int main(int argc, const char * argv[]) {
vector<int> values = {1,3,5,9};
vector<int> weights = {2,3,4,7};
Knapsack k(10, values, weights);
k.pack();
cout << "最大容纳物品总价值:" << endl;
cout << k.getMaxValue() << endl;
vector<int> plan = k.getPlan();
cout << "物品件数序列:" << endl;
for (auto i : plan){
cout << i << "\t";
}
cout << endl;
return 0;
}