算法设计与分析代码实现笔记

dynamic programming

矩阵链式乘法

确定结合律使用顺序以达到最小乘法次数

错误使用递归实现动态规划的例子

复杂度 O ( 2 n ) O(2^n) O(2n),由递推方程通过数学归纳法可证

#include <vector>
#include <iostream>
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 <vector>
#include <stack>
#include <iostream>
#include <fstream>
#include <list>
#include <sys/stat.h>

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 n1次循环,内层等差数列求和,有 ( 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(n1)(1+m)mc(n×m2)c为某一常数

#include <vector>
#include <stack>
#include <iostream>
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 <vector>
#include <stack>
#include <iostream>
#include <fstream>
#include <list>
#include <sys/stat.h>

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

运行结果:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值