首页 > 其他分享 >【笔记】二维DP

【笔记】二维DP

时间:2024-09-13 09:23:10浏览次数:10  
标签:int 二维 笔记 range DP ans 序列 dp 描述

文章目录


二维DP和普通DP本质相同,只是状态的维度变成二维,即需要两个变量来定义子问题

二维DP的更新可能涉及部分优化:前缀和、滚动数组

核心就是怎么从子问题到原问题

例题

lanqiao1536数字三角形

在这里插入图片描述

题目描述

给出一个数字三角形,从顶部到底部可以沿左斜线向下或者右斜线向下,要求数字之和最大,求最大和。

输入描述
  • 第一行:包含一个整数N,表示三角形的行数
  • 下面N行给出数字三角形,每个数字都是0-99之间的整数。
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出描述

输出一个整数,表示最大和

30
解题思路

对于这个题目来说,从上面开始一层层往下加和从下面一层层往上加能得到的最大值应该是一致的。

选取状态1

dp[i][j]表示从第i行第j个往下走的最大和

(1,1)
(2,1)(2,2)
(3,1)(3,2)(3,3)

dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j]

  • dp[i][j]表示从(i,j)出发到底部的最大和
  • a[i][j]表示第i行第j个元素的值
  • 最终答案等于第n行dp[n][x]里面最大的一个
代码1
n=int(input())
# 这里用n+1是因为列表下标从1开始
# 用a数组来存储三角形的数值
a=[[0]*(n+1)]
for i in range(n):
    a.append([0]+list(map(int,input().split())))
# 用dp来存储第i行第j个数最大和
dp=[[0]*(n+1) for i in range(n+1)]
# 三角形尖端的值为a的第一行第一个值
dp[1][1]=a[1][1]
for i in range(2,n+1):
    for j in range(1,i+1):
        if j==1:
            dp[i][j]=dp[i-1][j]+a[i][j]
        elif j==i:
            dp[i][j]=dp[i-1][j-1]+a[i][j]
        else:
            dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j]

ans=0
for j in range(1,n+1):
    ans=max(ans,dp[n][j])

print(ans)
选取状态2

dp[i][j]表示从第i行第j个往上走的最大和

(1,1)
(2,1)(2,2)
(3,1)(3,2)(3,3)

dp[i][j]=max(dp[i+1][j+1],dp[i+1][j])+a[i][j]

  • dp[i][j]表示从(i,j)出发到底部的最大和
  • a[i][j]表示第i行第j个元素的值
  • 最终答案等于dp[1][1]
代码2
n=int(input())
a=[[0]*(n+1)]
for i in range(n):
    a.append([0]+list(map(int,input().split())))
# 初始化存储最大和的数组
dp=[[0]*(n+1) for i in range(n+1)]
# 从下往上累加
for i in range(n,0,-1):
    for j in range(1,i+1):
    # 边界条件:最后一行的值等于原来的值
        if i==n:
            dp[i][j]=a[i][j]
        else:
            dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+a[i][j]
print(dp[1][1])

lanqiao 389摆花

题目描述

小明在花店门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。规定第i种花不能超过 a i a_{i} ai​盆,摆花时同种花放在一起,且不同种类花需按标号的从小到大排列。

问:一共有多少种不同的摆花方案?

输入描述

第一行包含两个正整数 n和 m,中间用一个空格隔开。

第二行有 n 个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、…an 。
其中,0<n≤100,0<m≤100,0≤ai≤100,0<n≤100,0<m≤100,0≤ai≤100。

2 4
3 2
解题思路
  • 状态:dp[i][j]表示前i种花,数量为j盆的方案数,答案为dp[n][m]
  • 状态转移:dp[i][j]=dp[i-1][j]+…+dp[i-1][j-a[i]]表示从前i-1种花到第i种花,摆0盆、1盆…、a[i]盆的情况。
  • 边界:dp[…][0]=1表示前几种花都没摆的情况
输出描述

输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对 1 0 6 + 7 10^6+7 106+7 取模的结果。

2
代码
a=[0]+list(map(int,input().split()))
# 状态dp[i][j]前i种花、总数是j盆的方案数,答案是dp[n][m]
dp=[[0]*(m+1) for _ in range(n+1)]
# 状态转移方程:第i种花可以摆0-a[i]盆,所以从第i-1到第i的状态转移方程为:dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+……+dp[i-1][j-a[i]]
# 边界条件:前面几种花一盆都不放的方案数是1,dp[i][0]=1
# 注意:这里的初始化从0开始,为了给后面的赋值
for i in range(n+1):
  dp[i][0]=1
for i in range(1,n+1):
  for j in range(1,m+1):
    for k in range(min(a[i],j)+1):
      dp[i][j]+=dp[i-1][j-k]
      dp[i][j]%1000007
print(dp[n][m])

lanqiao3711选数异或

题目描述

给定n个正整数a[i],询问其中有多少个不同的子序列进行异或运算的值为x?

由于结果很大,需要对998244353取模

异或运算:位运算的一种,相同为0,不同为1,参考这个

输入描述

第一行:两个正整数n,x(x<64)

第二行:输入n个正整数

输出描述

输出方案数,对998244353取模

解题思路

原问题:给定n个正整数,求有多少个子序列进行异或运算的值为x,方案数

子问题:前i个正整数,有多少个子序列异或值为j,的方案数

状态:dp[i][j]表示前i个数,子序列异或为j的方案数

状态转移方程:对于第i个数,有选和不选两种可能

    • xxx^a[i]=j⇒xxx^a[i]^a[i]=j^a[i]⇒xxx=j^a[i]
    • dp[i][j]=dp[i-1][j^a[i]]
  • 不选
    • dp[i][j]=dp[i-1][j]
n,x=map(int,input().split())
a=[0]+list(map(int,input().split()))
dp=[[0]*64 for i in range(n+1)]
#只有一个数时,无论选还是不选,都各只有一种可能
dp[1][0]=1
dp[1][a[1]]=1
for i in range(2,n+1):
    for j in range(64):
        dp[i][j]=(dp[i-1][j]+dp[i-1][j^a[i]])%998244353
print(dp[n][x])

lanqiao3348可构造的序列总数

- 题目描述
    - 给定两个数字k和n,需要构造序列满足:
        - 序列长度为n
        - 序列中每个元素区间[1,k]
        - 序列中的下一个元素是上一个元素的倍数
        - 答案很有可能很大,需要对1e9+7取模
- 输入格式
    - 输入一行k,n
- 输出格式
    - 输出一个整数表示答案,答案需要对1e9+7取模
- 解题思路
    - dp[i][j]表示以j结尾的长度为i的序列
    - 状态转移方程就是找i-1长度的j的因数
    - 找j的因数时对其开根号,优化时间复杂度
k, n = map(int, input().split())
mod = int(1e9) + 7
N = 2000

# dp -> 以j数字结尾,长度为i的倍数序列
dp = [[0] * (N + 10) for i in range(N + 10)]
dp[1] = [0] + [1] * (N + 9)
for i in range(1, N + 10): dp[i][1] = 1

# 找num的因数
def check(num):
    ans = []
    for i in range(1, int(num**0.5) + 1):
        if num % i→0:
            ans.append(i)
            ans.append(num // i)
    return set(ans) # 用set去重

# 递推dp数组
for i in range(2, n + 1):
    for j in range(2, k + 1):
        for q in check(j): # q为j的因数
            dp[i][j] += dp[i - 1][q]

ans = 0
for i in range(1, k + 1):
    ans += dp[n][i]
    
print(ans % mod)

标签:int,二维,笔记,range,DP,ans,序列,dp,描述
From: https://blog.csdn.net/m0_73676887/article/details/142161593

相关文章

  • 【Python学习笔记】 第7章 字符串基础
    本章范围本章主要讲str字符串类型,有关的操作适用于Unicode处理。Unicode简介ASCII是Unicode的简单形式,但Unicode适用于非英语地区的人们。两者在文件中的编码不同。在Python3.X中,有三种字符串类型:str用于Unicode文本,bytes用于二进制数据,bytearray是bytes的一种可修改的变体......
  • 洛谷P10504 守卫者的挑战 题解 概率DP
    题目链接:https://www.luogu.com.cn/problem/P10504状态\(f_{i,s,k}\)表示:当前正面临第\(i\)项挑战(此时第\(1\simi-1\)项挑战已完成,第\(i\)项挑战还没开始);目前已经挑战成功了\(s\)项(即第\(1\simi-1\)项挑战中共有\(s\)项挑战成功,\((i-1)-s\)项没挑战成功);......
  • Java面试笔记记录6
    1.Spring是什么?特性?有哪些模块?Spring是一个轻量级、非入侵式的控制反转Ioc和面向切面AOP的框架。特性:1.Ioc和DISpring的核心就是一个大的工厂容器,可以维护所有对象的创建和依赖关系,Spring工厂用于生成Bean,并且管理Bean的生命周期,实现高内聚低耦合的设计理念。2.AOP编程Sp......
  • Python3 学习笔记6-os 模块、错误和异常、面向对象编程、类的专有方法、命名空间和作
    目录一、os模块: 常用方法: 二、错误和异常:(1)语法错误:(2)异常:(3)异常处理:(4)抛出异常:(5)用户自定义异常:(6)清理行为:(7)with语句:三、面向对象编程: (1)类和对象:(2)继承:(3)封装:(4)多态:(5)运算符重载: 四、类的专有方法:(1)__init__(self,...):(2)__del__(self):(3)__repr__(self):(4)__set......
  • datastructure与算法 orderedPair
    /**  Aninterfacethatdescribestheoperationsofasetofobjects.  @authorCharlesHoot,FrankM.Carrano  @version4.0*/publicinterfaceSetInterface<T>{  /**Getsthecurrentnumberofentriesinthisset.    @return Theintegernum......
  • 【影像组学pyradiomics学习笔记】png图像提取组学特征
    1、提取单张png图像组学特征示例:importSimpleITKassitkimportnumpyasnpimportmatplotlib.pyplotaspltfromradiomicsimportfeatureextractorimportosimportcv2defload_image(image_path):image=cv2.imread(image_path,cv2.IMREAD_GRAYSCALE)#......
  • 【学习笔记】状压DP
    状态压缩DP对于一个集合,他一有\(2^n\)个子集,而状态压缩就是枚举这些子集,每一个状态就是一个由\(01\)构成的集合,如果为\(0\)就表示不选当前的元素,否则就表示选。因为状态压缩将每一个状态压缩成了一个用二进制表示的数,所以不光可以节省空间,还可以节省时间。因为是枚举子集,所以时......
  • MathType纯新手安装笔记自述
    一、找到自己E盘中下载的Mathtype7.4安装包及补丁二、安装MathType-win-zh三、管理员身份运行MathType7PJ四、打开WORD——》点击选项——》点击信任中心——》点击信任中心设置——》点击受信任位置五、双击右侧用户位置的第三行,弹出窗口,复制路径。六、按键“win+e”七......
  • 3D异常检测最新论文《Complementary Pseudo Multimodal Feature for Point Cloud Anom
        本文是曹云康24年投稿至《PattenRecognition》的文章,是目前在MVTec3D-AD数据集上的3D异常检测SOTA。之所以被分类到3D异常检测类别,是因为这篇文章中仅使用了点云数据进行检测,未使用RGB模态。同样,文章中也指出了它所使用的多模态其实是“伪模态”,是将点云投影到2......
  • MySQL学习笔记(四)MySQL慢查询优化
    慢日志查询慢速查询日志由执行时间超过long_query_time几秒并且至少需要min_examined_row_limit检查行的SQL语句组成long_query_timeSELECT@@long_query_time;--默认是10单位sSETGLOBALlong_query_time=1;--设置超过1s就算慢查min_examined_row_limitSEL......