算法【动态规划】 | 【01】二维表结构

一、问题解决思路:

先尝试用递归写法 -> 建立数组讲数据缓存到数组中 -> 建立表格结构优化

- 先确定限界条件;
- 根据设定变量构建表格;
- 在根据调用函数需要的状态来确定表格中获取结果的位置【以下图中的★】
- 根据限界条件先将部分表格填充获取去除;
- 在根据其他条件对表格进行填充,至填到★即结果;

二、问题一:

1、问题描述

当在n个位置中,从起始位置到结尾位置必须走k步到达终点,一共有几种走法?

2、图文解析

在这里插入图片描述

3、递归代码

/*----------------------------------------------------------------------
	> File Name: base.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Thu 17 Mar 2022 08:41:03 AM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <vector>


/**
 * @param e: 列表长度
 * @param t: 目标
 * @param rest: 剩余步数
 * @param cur: 当前位置
 * */
int solve(int e, int t, int rest, int cur) {
    if(rest == 0) {
        return cur == t ? 1 : 0; 
    }
    if(cur == 1) {
        solve(e, t, rest-1, 2);
    }

    if(cur == e) {
        solve(e, t, rest-1, e-1);
    }

    return solve(e, t, rest-1, cur+1) + solve(e, t, rest-1, cur-1); 
}

int main(int argc, char* argv[])
{
    int step = 4;
    int target = 4;
    int cur = 2;

    std::cout << solve(5, target, step, cur) << std::endl;
    return 0;
}

4、动态规划代码

/*----------------------------------------------------------------------
	> File Name: dynamicBase.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Fri 18 Mar 2022 09:14:32 PM CST
----------------------------------------------------------------------*/

#include <iostream>


/**
 * @param e: 列表长度
 * @param t: 目标
 * @param rest: 剩余步数
 * @param cur: 当前位置
 * @param arr: 存储是数据信息
 * */

int solve(int e, int t, int rest, int cur, int arr[][6]) {

    if(arr[rest][cur] != -1) {
        return arr[rest][cur];
    }
    if(rest == 0) {
        arr[rest][cur] = cur == t ? 1 : 0; 
    }else if(cur == 1) {
        arr[rest][cur] = solve(e, t, rest-1, 2, arr);
    }else if(cur == e) {
        arr[rest][cur] = solve(e, t, rest-1, e-1, arr);
    }else {
        arr[rest][cur] = solve(e, t, rest-1, cur+1, arr) + solve(e, t, rest-1, cur-1, arr); 
    }
    return arr[rest][cur];
}


int main(int argc, char* argv[])
{
    
    int arr[6][6];
    for(int i=0; i<6;++i) {
        for(int j=0; j<6; ++j) {
            arr[i][j] = -1;
        }
    }
    int step = 4;
    int target = 4;
    int cur = 2;

    int rt = solve(5, targert, step, cur, arr);
    std::cout << arr[step][target];
    return 0;
}

二、问题二

1、问题描述

题中给出数组arr = [3,100,4,50],A、B两人分别从数组中取出数组,只能从最左或者最右取出数值,当列表取完后,比较A、B
两个的累加和判度最大的一方;

2、图文解析

在这里插入图片描述

3、递归代码

/*----------------------------------------------------------------------
	> File Name: base.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Sat 19 Mar 2022 03:40:35 PM CST
----------------------------------------------------------------------*/

#include <vector>
#include <iostream>


/**
 * 玩家A、B:A先取列表中【最左或者最右的数,最大的】,在轮到B取;
 * 后续判断两者取到的数最大
 * */
int f(std::vector<int> vc, int l, int r);


int s(std::vector<int> vc, int l, int r) {
    if(l == r)
        return 0;
    return f(vc, l+1, r) > f(vc, l, r-1) ? 
        f(vc, l+1, r) : f(vc, l, r-1);
}

int f(std::vector<int> vc, int l, int r) {
    if(l == r)
        return vc[l];

    return vc[l] + s(vc, l+1, r) > vc[r] + s(vc, l, r-1) ? 
        vc[l] + s(vc, l+1, r) : vc[r] + s(vc, l, r-1);
}


int solve(std::vector<int> vc) {

    return f(vc, 0, vc.size() -1) > s(vc, 0, vc.size()-1) ? 
        f(vc, 0, vc.size() -1) : s(vc, 0, vc.size()-1);
}

int main(int argc, char* argv[])
{
    std::vector<int> vc = {3, 100, 4, 50};
    std::cout << solve(vc) << std::endl;
    return 0;
}

4、动态规划代码

/*----------------------------------------------------------------------
	> File Name: dynamicBase.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Sat 19 Mar 2022 04:14:32 PM CST
----------------------------------------------------------------------*/

#include <iostream>
#include <vector>

int solve(std::vector<int> vc) {
    if(vc.empty())
        return 0;
    int len = vc.size();
    int f[len][len] = {0};
    int s[len][len] = {0};

    for(int i=0; i<len; ++i) {
        f[i][i] = vc[i];
    }

    int row = 0, col=1;
    while(col < len) {
        int i = row;
        int j = col;
        while(i < len && j < len) {
            /* f的位置是选择列表中的值以及s表中的下一行或者前一列的值 */
            f[i][j] = (vc[i] + s[i+1][j]) > (vc[j] + s[i][j-1]) ? 
                (vc[i] + s[i+1][j]) : (vc[j] + s[i][j-1]);

            s[i][j] = f[i + 1][j] < f[i][j-1] ? 
                f[i + 1][j] : f[i][j-1];
            std::cout << "f:" << f[i][j] << " " << i << "-" << j << std::endl;
            std::cout << "s:" << s[i][j] << " " << i << "-" << j << std::endl;
            j++;
            i++;
        }
        col++;
    }
    return f[0][len-1] > s[0][len-1] ? f[0][len-1] : s[0][len-1];
}

int main(int argc, char** argv){
    std::vector<int> vc = {3, 100, 4, 50};
    std::cout << solve(vc) << std::endl;

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jxiepc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值