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

【DP 动态规划 | 精选推荐】持续更新

在这里插入图片描述

文章目录

    • 前言
      • 1. 乘积为正数的最长子数组长度
      • 2. 矩阵中和能被 K 整除的路径
      • 3. 使序列递增的最小交换次数
      • 4. Kate and Company Management
      • 5. Good Key, Bad Key
      • 6. Vladik and Memorable Trip

前言

本文(DP 动态规划)章节,主要记录一些比较经典,或者说是容易理解的动态规划习题,难度一般都不会很大( ≤ M e d i u m \leq Medium Medium)。

1. 乘积为正数的最长子数组长度

乘积为正数的最长子数组长度

状态定义:

  • f [ i ] [ 0 / 1 ] f[i][0 / 1] f[i][0/1]:以 i i i 结尾的乘积为正( 0 0 0)/负( 1 1 1)的最大长度。
  • 转移见代码注释那几行,容易理解。

由于转移只用到上一层状态,所以可以用两个变量来替代。

class Solution {
public:
    int getMaxLen(vector<int>& nums) {
        int n = nums.size(); 
        // int f[n + 1][2];
        int res = 0;
        // f[0][0] = f[0][1] = 0;
        int f = 0, g = 0;
        for (int i = 1; i <= n; i++) {
            int x = nums[i - 1];
            if (x == 0) f = g = 0; //f[i][0] = f[i][1] = 0;
            else if (x > 0) {
                // f[i][0] = f[i - 1][0] + 1;
                // f[i][1] = f[i - 1][1] ? (f[i - 1][1] + 1) : 0;
                f++;
                g = g ? (g + 1) : 0;
            } else if (x < 0) {
                // f[i][0] = f[i - 1][1] ? (f[i - 1][1] + 1) : 0; 
                // f[i][1] = f[i - 1][0] + 1;
                int t = f;
                f = g ? g + 1 : 0;
                g = t + 1;
             }

            res = max(res, f);
        }
        return res;
    }
};

2. 矩阵中和能被 K 整除的路径

矩阵中和能被 K 整除的路径

状态定义:

  • f [ i ] [ j ] [ k ] : f[i][j][k]: f[i][j][k] 走到 [ i , j [i,j [i,j]余数为 k k k的路径数。
  • 转移:用余数进行转移就行了。
class Solution {
public:
    
    int numberOfPaths(vector<vector<int>>& grid, int k) {
        int n = grid.size(), m = grid[0].size(); 
        vector<vector<vector<int>>> f(n, vector<vector<int>>(m, vector<int>(52, 0)));
        constexpr static int mod = 1e9 + 7;
        
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                for (int x = 0; x < k; x++) f[i][j][k] = 0;
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                for (int x = 0; x < k; x++) {
                    int now = grid[i][j];
                    now %= k;
                    int t = (now + x) % k;
                    if (i == 0 && j == 0) {
                        f[i][j][now] = 1;
                        break; 
                    } else if (i == 0) {
                        f[i][j][t] += f[i][j - 1][x];
                        f[i][j][t] %= mod;
                    } else if (j == 0) {
                        f[i][j][t] += f[i - 1][j][x];
                        f[i][j][t] %= mod;
                    } else {
                        f[i][j][t] += f[i - 1][j][x] + f[i][j - 1][x];
                        f[i][j][t] %= mod;
                    }
                }
            }
        }
        return f[n - 1][m - 1][0] % mod;
    }
};

3. 使序列递增的最小交换次数

使序列递增的最小交换次数

状态定义:

  • f [ i ] [ 0 / 1 ] : f[i][0/1]: f[i][0/1] i i i 为结尾的,且当前第 i i i 位交换(1)/ 不交换(0)的最小交换次数。
class Solution {
public:
    int minSwap(vector<int>& a, vector<int>& b) {
        int n = a.size(); 
        int f[n][2];
        memset(f, 0x3f, sizeof f);
        f[0][0] = 0, f[0][1] = 1;
        for (int i = 1; i < n; i++) {
            if (a[i] > a[i - 1] && b[i] > b[i - 1]) {
                f[i][0] = min(f[i][0], f[i - 1][0]);
                f[i][1] = min(f[i][1], f[i - 1][1] + 1);
            } 
            if (a[i] > b[i - 1] && b[i] > a[i - 1]) {
                f[i][0] = min(f[i][0], f[i - 1][1]);
                f[i][1] = min(f[i][1], f[i - 1][0] + 1);
            }
        }
        return min(f[n - 1][1], f[n - 1][0]);
    }
};

4. Kate and Company Management

Kate and Company Management

题意:

n个数,划分不同组,每组相邻的两数gcd不为1,不相邻的可以不满足该条件。问组的最大划分个数,若个数 ≤ 3 \leq 3 3输出 − 1 -1 1

思路:

dp + 分解质因数

状态定义:

  • f [ i ] : f[i]: f[i] i i i 位为结尾最大组成个数。
  • p r e [ x ] : pre[x]: pre[x] 因数为 x x x 的最大组成个数。

状态转移:

a [ i ] a[i] a[i] 的所有因数 x 1 , x 2 , . . . , x n x_1, x_2,..._,x_n x1,x2,...,xn

  • f [ i ] = f [ x i ] + 1 f[i] = f[x_i] + 1 f[i]=f[xi]+1

在转移完 f [ i ] f[i] f[i] 后,需要更新当前 a i a_i ai 的所有因数在此时能组成的最大个数:

  • p r e [ x ] = f [ i ] pre[x] = f[i] pre[x]=f[i]
int n;
int a[N];
int f[N], pre[N]; 
vi v[N];

// nlogn 打出质因数
void init() {
	for (int i = 1; i <= a[1]; i++) {
		for (int j = 1; j <= a[1] / i; j++) {
			v[i * j].pb(i);
		}
	}
}

void solve() {
	cin >> n;
	rep(i, 1, n) cin >> a[i];
	sort(a + 1, a + 1+ n, [=](int i, int j){ return i > j; }); 
	init(); 
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < v[a[i]].sz; j++) {
			int x = v[a[i]][j];
			f[i] = max(f[i], pre[x] + 1); 
		}
		for (int j = 1; j < v[a[i]].sz; j++) {
			int x = v[a[i]][j];
			pre[x] = f[i];
		} 
	}
	int res = 0;
	for (int i = 1; i <= n; i++) res = max(res, f[i]);
	if (res < 3) res = -1;
	cout << res << endl; 
}

5. Good Key, Bad Key

Good Key, Bad Key

题意:

n个箱子,每个箱子打开有收益 a i a_i ai,选择好钥匙打开需要花费固定值 m m m,坏钥匙打开第 i i i 个箱子花费0,但是会导致后面 i , i + 1 , . . . n i,i+1,...n i,i+1,...n 的箱子收益减半。问最大收益。

状态定义:

  • f [ i ] [ j ] : f[i][j]: f[i][j] 开了 i i i 个箱子,使用了 j j j 把坏钥匙的最大收益。

另解: 贪心

结论是,bad key 后面一定不存在 good key,即 ggggggbbbbb

x, y
1. good then bad: x + y / 2 - m
2. bad then good: x / 2 + y / 2 - m
int n, m;
int f[N][65], a[N], s[N];

void solve() {
	int n, m; cin >> n >> m;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    
    for(int i = 1; i <= n; i ++) {
        f[i][0] = f[i - 1][0];
        // f[i][0] = s[i] - m * i;
        for(int j = 1; j <= 63; j ++) {
            f[i][j] = max(f[i - 1][j - 1] + (a[i] >> j), f[i - 1][j] - m + (a[i] >> j));
        }
    }
    int ans = -2e18;
    for(int i = 1; i <= 63; i ++) ans = max(ans, f[n][i]);
    cout << ans << endl;
    return ;
}

6. Vladik and Memorable Trip

Vladik and Memorable Trip

题意:

n 个数,挑一些区间,所有值进行异或求最大。但是需要满足条件是,区间中出现的数 x x x,不能在出现在挑选的区间外。

状态定义:

  • f [ i ] : f[i]: f[i] i i i 个人中挑选区间的最大值。

状态转移:

维护每个值的最左和最右下标,枚举包含以 i i i 为结尾的区间的情况转移。

O ( n 2 ) d p O(n^2) dp O(n2)dp s t st st数组用来去重,一个数只运算一次(相同的数异或不就白给,想读题点上方传送门)。

int n;
int a[N];
int L[N], R[N];
int f[N];
bool st[N];

void solve() {
	cin >> n;
	memset(L, 0x3f, sizeof L);
	rep(i, 1, n) { 
		cin >> a[i];
		L[a[i]] = min(L[a[i]], i);
		R[a[i]] = max(R[a[i]], i);
	}
	for (int i = 1; i <= n; i++) {
		f[i] = f[i - 1];
		memset(st, 0, sizeof st);
		int l = L[a[i]];
		int res = 0;
		for (int j = i; j >= 1; j--) {
			if (!st[a[j]]) {
				if (R[a[j]] > i) break; 
				l = min(l, L[a[j]]);
				res ^= a[j];
				st[a[j]] = 1;
			}
			if (j <= l) f[i] = max(f[i], f[j - 1] + res);
		}
	}
	cout << f[n] << endl;
}

相关文章:

  • 专利的要求-需要什么条件?
  • Google Earth Engine (GEE)——GEE制作gif动态图(北京市为例)
  • Spring-Framework-ioc-1
  • Vue 动态换肤
  • 从零到一搭建基础架构-玩转maven依赖版本管理
  • CE修改器学习历程之下载、安装和汉化
  • 【鸟哥杂谈】物联网体系知识梳理
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • C语言必刷题——期末不挂科
  • 基于微信小程序+SSM+Vue+Node实现智慧旅游商城系统
  • RabbitMQ常用消息模式
  • Spring中的11个扩展点
  • AcWing 蓝桥杯AB组辅导课 01、递归与递推
  • 2022软考高项十大领域知识整理(三)--项目质量管理、沟通管理
  • spring boot在线投票系统 毕业设计源码141307
  • Date型的使用
  • github指令
  • iOS 颜色设置看我就够了
  • java 多线程基础, 我觉得还是有必要看看的
  • Linux各目录及每个目录的详细介绍
  • RxJS: 简单入门
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 对超线程几个不同角度的解释
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 推荐一个React的管理后台框架
  • 温故知新之javascript面向对象
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • 国内唯一,阿里云入选全球区块链云服务报告,领先AWS、Google ...
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​批处理文件中的errorlevel用法
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #HarmonyOS:Web组件的使用
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (4)(4.6) Triducer
  • (4.10~4.16)
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (Oracle)SQL优化技巧(一):分页查询
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .project文件
  • .set 数据导入matlab,设置变量导入选项 - MATLAB setvaropts - MathWorks 中国
  • .sh文件怎么运行_创建优化的Go镜像文件以及踩过的坑
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [acm算法学习] 后缀数组SA
  • [BSGS算法]纯水斐波那契数列
  • [C/C++]数据结构 循环队列
  • [CC-FNCS]Chef and Churu
  • [CTF]2022美团CTF WEB WP