当前位置: 首页 > news >正文

机试准备第19天

今天重点学习动态规划问题。在使用递归解决问题时可能会产生性能问题,动态规划算法是为了解决递归产生的性能问题。递归会产生大量的重复问题,可以用空间换时间,用一种数据结构记录所有已经解决的问题。以数据结构为核心,从小问题回归得到大问题。首先设计一个数据结构,记录不同规模的答案,数据结构采用从小到大的方式去生成。

第一题是放苹果,通过一个二维dp数组记录信息。

#include <stdio.h>
#include <cstring>
using namespace std;
int main()
{
    int dp[13][13] = {0};
    //dp[m][n]就是m个苹果放入n个盘子
    int m, n;
    while(scanf("%d%d", &m, &n)!=EOF){
        memset(dp, 0, 13*13);
        for(int i = 0;i<=m;i++){
            dp[i][1] = 1;//只有一个盘子
        }
        for(int i = 1;i<=n;i++){
            dp[1][i] = 1;//只放一个苹果
            dp[0][i] = 1;//1个苹果都不放
        }
        for(int i = 2;i <=  m;i++){
            for(int j = 2; j <=n;j++){
                if(i >= j){//applenum > platenum
                    dp[i][j] = dp[i][j-1] + dp[i-j][j];
                }
                else {
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        printf("%d\n",  dp[m][n]);
    }

    return 0;
}

第二题是吃糖果。简单动归,可以吃一块或者两块。

#include <stdio.h>
using namespace std;
int main(){
    int dp[20]={0};
    dp[1] = 1;//一块巧克力只有一种方案
    dp[2] = 2;//两块巧克力有两种方案
    int N;
    scanf("%d", &N);
    for(int i = 3;i<=N;i++){
        dp[i] = dp[i - 1]+dp[i-2];//可以选择吃一块或者吃两块
    }
    printf("%d", dp[N]);
}

下面学习和线性数据结构相关的动态规划问题,两个序列求最长公共子序列,一个序列内的最大子序列和等等。两个线性表或一个线性表和他本身做对比,希望得到最值,这种需要动态规划。

第三题是最长公共子序列。dp[i][j]表示0~i-1 0~j-1的子序列的最长公共长度,若当前遍历元素相同,则dp[i][j]=dp[i-1][j-1]+1,若不同,则dp[i][j]=max(dp[i][j-1], dp[i-1][j])。

#include <stdio.h>
#include  <string.h>
#include <algorithm>
using namespace std;
int dp[1002][1002];
int main(){
    int n, m;
    char s1[1001];
    char s2[1001];
    scanf("%d%d", &n, &m);
    scanf("%s%s", s1, s2);
    //dp[i][j] s1的前i个元素 s2前j个元素的最大公共长度
    
    for(int j = 0; j<=m;j++){
        dp[0][j] = 0;//s1的一个元素也没处理
    }
    for(int i = 0; i<=n;i++){
        dp[i][0] = 0;
    }
    for(int i = 1;i<=n;i++){
        for(int j = 1;j<=m;j++){
            //s1[0]~si[i-1] s2[0]~s2[j-1]
            if(s1[i-1] == s2[j - 1]){
                dp[i][j] = dp[i-1][j-1] + 1;
            }
            else {
                dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
            }
        }
    }
    printf("%d\n", dp[n][m]);
    
    
}

第四题是最长公共字串。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
short dp[10001][10001];
int main(){
    char s1[10001];
    char s2[10001];
    scanf("%s%s", s1,s2);
    int n = strlen(s1);
    int m = strlen(s2);
    for(int j = 0; j <= m;j++){
        dp[0][j] = 0;
    }
    for(int i = 0;i<=n;i++){
        dp[i][0] = 0;
    }
    short curmax = 0;
    for(int i = 1; i <= n;i++){
        for(int j = 1;j<=m;j++){
            if(s1[i-1]>='a'&&s1[i-1]<='z'&&s1[i-1] == s2[j-1]){
                dp[i][j] = dp[i-1][j-1]+1;
                curmax = max(dp[i][j], curmax);
            }
            else {//连不起来
                dp[i][j]=0;
                
            }
        }
    }
    printf("%d\n", curmax);
    return 0;
}

第五题是最大子序列和,dp数组代表从头到下标i元素的最大序列和。

#include <vector>
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int N;
    scanf("%d", &N);
    vector<long> vec1;
    for(int i = 0; i<N;i++){
        int val;
        scanf("%d", &val);
        vec1.push_back(val);
    }
    int size = vec1.size();
    vector<long> res;
    res.push_back(vec1[0]);
    long curmax = res[0];
    for(int i = 1; i< vec1.size();i++){
        long curnum = max(res[i-1]+vec1[i], vec1[i]);
        res.push_back(curnum);
        curmax = max(curmax, curnum);
    }
    printf("%ld", curmax);
}

第六题是最大子矩阵。

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d", &n)!=EOF){
        if(n == 0) break;
        vector<int> start(10002);//记录当前元素为结尾的最大连续子序列的起始下标
        vector<int> vec(10002);//记录数组元素
        vector<int> dp(10002);//以i为下标元素对应的最大连续子序列和
        for(int i = 0; i<n;i++){
            scanf("%d", &vec[i]);
        }
        dp[0] = vec[0];
        start[0] = 0;
        int curmax = dp[0];
        for(int i = 1; i<n;i++){
            int val1 = dp[i-1]+vec[i];
            int val2 = vec[i];
            if(val1>=val2){
                dp[i] = val1;
                start[i] = start[i-1];
            }
            else {
                dp[i] = vec[i];
                start[i] = i;
            }
            curmax = max(curmax, dp[i]);
        }
        if(curmax<0) printf("0 %d %d\n",vec[0],vec[n-1]);
        else {
            for(int i = 0;i < n;i++){
                if(dp[i] == curmax){
                    printf("%d %d %d\n", curmax, vec[start[i]], vec[i]);
                    break;
                }
            }
        }
    }
}

第七题是最大上升序列和。

#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d", &n)!=EOF){
        int dp[1000];//下标为i 的最大上升序列和
        vector<int> vec;
        for(int i=0;i<n;i++){
            int val;
            scanf("%d", &val);
            vec.push_back(val);
        }
        int maxsum = 0;
        for(int i = 0; i<n;i++){
            dp[i] =vec[i];
            for(int j = 0; j<i;j++){
                if(vec[i]>vec[j]){
                    dp[i] = max(dp[j] + vec[i], dp[i]);
                }
            }
            maxsum = max(dp[i], maxsum);
        }
        
        printf("%d\n", maxsum);
    }
}

下面学习01背包问题,首先明确dp数组的含义,dp[i][j]代表下标为0~i之间的物品,任取然后放进容量为j的背包里。不放物品i,dp[i][j] = dp[i-1][j],放物品i,dp[i][j] = dp[i-1][j-weight[i]] + value[i]。dp[i][j]为两者的最大值。明天继续。

相关文章:

  • 4.angular 服务
  • 5.3《凸透镜成像的规律》——先于5.2《生活中的透镜》讲
  • Windows 部署 RuoYi 前后端分离项目
  • Mac下Ollama安装全攻略:开启本地大模型之旅
  • Qt Creator入门
  • 蓝桥杯[每日一题] 模拟题:蚂蚁感冒(java版)
  • Java面试黄金宝典1
  • 笔记本运行边缘计算
  • 使用React和google gemini api 打造一个google gemini应用
  • 【数据挖掘】Python基础环境安装配置
  • 卸载conda,poetry常用命令,vscode使用poetry虚拟环境
  • 【万字总结】前端全方位性能优化指南(三)——GPU渲染加速、WebGPU、OffscreenCanvas多线程渲染
  • 电商项目Ts版本
  • 【HarmonyOS Next】鸿蒙中自定义弹框OpenCustomDialog、CustomDialog与DialogHub的区别详解
  • 标准卡尔曼滤波
  • 采购供应链管理培训及供应链网络优化案例P109(109页PPT)(文末有下载方式)
  • python爬虫笔记(一)
  • Vue响应式数据丢失的可能原因
  • C语言:能够规定次数,处理非法字符的猜数游戏(三重循环)
  • 【一起来学kubernetes】17、Configmap使用详解
  • 美国防部监察机构扩大“群聊门”事件调查范围
  • 体坛联播|欧冠巴萨3比3战平国米,柯洁未进入国家集训队
  • 世界黄金协会:一季度全球黄金投资需求同比增170%
  • 中国证券监督管理委员会党委委员、副主席王建军接受审查调查
  • “五一”逃离城市计划:带上帐篷去大自然里充电
  • 日菲同意扩大安全合作,外交部:反对任何在本地区拉帮结派的做法