算法基础精选题单 动态规划(dp)(递推+线性dp)(个人题解)

news2024/10/6 20:37:57

前言:

  一些简单的dp问题。

正文:

题单:237题】算法基础精选题单_ACM竞赛_ACM/CSP/ICPC/CCPC/比赛经验/题解/资讯_牛客竞赛OJ_牛客网 (nowcoder.com)

递推:

NC235911 走楼梯:

#include<bits/stdc++.h>
using namespace std;
long long dp[150];
int main(){
	int n;
	cin>>n;
	dp[1]=1;dp[0]=1;
	for(int i=2;i<=n;i++){
		dp[i]=dp[i-1]+dp[i-2];
	}
	cout<<dp[n];
	return 0;
}

dp中最经典的问题,就不展开说了。

线性dp:

NC22096 数字三角形:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	while(cin>>n){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=i;j++){
			cout<<j<<" ";
		}
		cout<<endl;
	}}
	return 0;
} 

这题不知道和dp有什么关系,直接两层循环输出就行了。

NC16708 过河卒:

#include<bits/stdc++.h>
using namespace std;
long long dp[55][55];
void con(int x,int y){
	dp[x][y]=-1;
	if(x+1>=0&&y+2>=0)dp[x+2][y+1]=-1;
	if(x+2>=0&&y+1>=0)dp[x+1][y+2]=-1;
	if(x+2>=0&&y+1>=0)dp[x-1][y+2]=-1;
	if(x-2>=0&&y+1>=0)dp[x-2][y+1]=-1;
	if(x-2>=0&&y-1>=0)dp[x-2][y-1]=-1;
	if(x-1>=0&&y-2>=0)dp[x-1][y-2]=-1;
	if(x+1>=0&&y-2>=0)dp[x+1][y-2]=-1;
	if(x+2>=0&&y-1>=0)dp[x+2][y-1]=-1;
}
int main(){
	int n,m,x,y;
	cin>>n>>m>>x>>y;
	con(x+1,y+1);
	dp[1][1]=1;
	for(int i=1;i<=21;i++){
		for(int j=1;j<=21;j++){
			if(dp[i][j]!=-1){
				if(dp[i-1][j]!=-1)dp[i][j]+=dp[i-1][j];
				if(dp[i][j-1]!=-1)dp[i][j]+=dp[i][j-1];
			}
		}
	}
	cout<<dp[n+1][m+1];
	return 0;
} 

在地图上标记好马的位置与马能走到的另外八个位置,在状态转移的时候记得注意该点状态永远为0。最后输出终点的状态。

NC16619 传球游戏:

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long dp[105][105];
int main(){
	cin>>n>>m;
	dp[0][1]=1;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			if(j==1){
				dp[i][j]=dp[i-1][n]+dp[i-1][j+1];
			}
			else if(j==n){
				dp[i][j]=dp[i-1][1]+dp[i-1][j-1];
			}
			else{
				dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
			}
		}
	}
	cout<<dp[m][1];
	return 0;
}

dp[i][j]表示在传球次数达到i次时球到达j手上的方法数,状态转移方程我们可以由球只能从左右两侧传来,所以知方程dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1],注意特判j=1和n的情况。

NC16810 [NOIP1999]拦截导弹:

#include <bits/stdc++.h>
using namespace std;
int a[1001],dp[1001];
int main()
{int p=0,flag=0;

   while(cin>>a[++p])
   {

   }
   p--;
   int ans=0;
   for(int i=1;i<=p;i++)
       { flag=0;
        for(int j=i-1;j>=1;j--)
           if (a[i]<=a[j]) flag=max(flag,dp[j]);
         if (flag==0) dp[i]=1;
         else dp[i]=flag+1;
         ans=max(ans,dp[i]);
         //cout<<dp[i]<<endl;
       }
       cout<<ans<<endl;
      memset(dp,0,sizeof(dp));
       ans=0;
   for(int i=1;i<=p;i++)
       { flag=0;
        for(int j=i-1;j>=1;j--)
           if (a[i]>a[j]) flag=max(flag,dp[j]);
         if (flag==0) dp[i]=1;
         else dp[i]=flag+1;
         ans=max(ans,dp[i]);
         //cout<<dp[i]<<endl;
       }
       cout<<ans<<endl;
    return 0;
}

Dilworth定理:最小链覆盖=最长反链长度,所以需要的系统就为这个序列的最长上升列长度,而一个系统最多能拦截的值就为反转的数列的最长上升子序列长度。求两个最长上升子序列即可。

NC16664 [NOIP2004]合唱队形:

#include<bits/stdc++.h>
using namespace std;
int a[1005];int dp1[1005],dp2[1005];
int main(){
	int n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	dp1[1]=1;
	for(int i=1;i<=n;i++){
		int m=0;
		for(int j=1;j<i;j++){
			if(a[i]>a[j]&&dp1[j]>m)m=dp1[j];
			//cout<<dp1[i]<<endl;
		}
		dp1[i]=m+1;
	}
	dp2[n]=1;
	for(int i=n;i;i--){
		int m=0;
		for(int j=n;j>i;j--){
			if(a[i]>a[j]&&dp2[j]>m)m=dp2[j];
		}
		dp2[i]=m+1;
	}
	for(int i=1;i<=n;i++){
		ans=max(ans,dp1[i]+dp2[i]-1);
	}
	//cout<<n<<" "<<ans<<endl;
	cout<<n-ans<<endl;
	return 0;
}

最长上升子序列的变式。先从左往右求一遍最长上升子序列(dp1),再从右往左求一遍(dp2)。
结果遍历一遍从左和从右的dp值和(dp1[i]+dp2[i]),找出和为最大的即为最大正常先递增再递减的子序列长度。

NC235954 滑雪:

#include<bits/stdc++.h>
using namespace std;
const int N = 310;
int n, m;
int g[N][N];
int f[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
int dp(int x, int y){
    int &v = f[x][y];
    if (v != -1) return v;

    v = 1;
    for (int i = 0; i < 4; i ++ ){
        int a = x + dx[i], b = y + dy[i];
        if (a >= 1 && a <= n && b >= 1 && b <= m && g[x][y] > g[a][b])
            v = max(v, dp(a, b) + 1);
    }

    return v;
}

int main(){
    cin>>n>>m;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            scanf("%d", &g[i][j]);
    memset(f, -1, sizeof f);
    int res = 0;
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= m; j ++ )
            res = max(res, dp(i, j));
    printf("%d\n", res);

    return 0;
}

经典的记忆化搜索的题,我觉得比起dp更像搜索。从最高点开始向四周搜索,结束时一定是最长的路径在dp中,因为搜索结束了就表示最长的那条线已经走完了。

NC235948 最大子串和:

#include<bits/stdc++.h>
using namespace std;
long long a[1000005],dp[1000005];
int main(){
	long long n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		dp[i]=max(dp[i-1]+a[i],dp[i]);
		ans=max(ans,dp[i]);
	}
	cout<<ans;
	return 0;
}

从某一个数字来看,它的最大连续子串和是前面一个数字的最大连续子串和加上它本身,和他本身取较大的那一个。当位于第一个的时候自然就是他自身所以可以实现一个动态规划。故递推式:dp[i] = max(dp[i-1]+dp[i], dp[i])。

NC235624 牛可乐和最长公共子序列:

#include<bits/stdc++.h>
using namespace std;
int dp[5005][5005];
int main(){
	string s,t;
	while(cin>>s>>t){
        if(s[0]==t[0])dp[1][1]=1;
		int ans=0;
		//memset(dp,0,sizeof(dp));
		int n=s.size(),m=t.size();
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				if(s[i-1]==t[j-1])dp[i][j]=dp[i-1][j-1]+1;
				else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
				ans=max(dp[i][j],ans);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

最长上升子序列的模板题。

后记:

  刷题的日子才过去两天怎么感觉我现在已经有点萎了,果然坚持下去是一件非常难的事啊。加油吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1852790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA期末复习题1

目录 Java 填空题整理及解析 1. 说出Java的特点&#xff1a; 2. Java的运行机制是先编译再解释运行。 3. 请按照以下分类补全对应的数据类型&#xff1a; 4. 在有限次数循环时&#xff0c;一般选择for循环结构&#xff1b;未知循环次数时&#xff0c;可以选择while循环结构…

一文读懂LLM API应用开发基础(万字长文)

前言 Hello&#xff0c;大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者&#xff0c;上一篇文章中我们详细介绍了LLM开发的基本概念&#xff0c;包括LLM的模型、特点能力以及应用&#xff1b;&#x1f632; 在本文中作者将通过&#xff1a…

用VPS部署聊天机器人有哪些优势?

VPS足以帮助您将人工智能 (AI) 的功能无缝融入聊天机器人并增强客户支持。聊天机器人已迅速成为改善用户体验的首选解决方案&#xff0c;因为它们全天候在线且可编程回答各种问题。 聊天机器人在客户支持方面的作用不容置疑。但所有出色的解决方案都需要出色的网络托管。 VPS…

三国之家网站的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;论坛管理&#xff0c;公告管理&#xff0c;三国视频管理&#xff0c;基础数据管理&#xff0c;三国图文管理 前台账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#…

(2024.6.23)最新版MAVEN的安装和配置教程(超详细)

1.什么是MAVEN Maven是一个自动化构建工具&#xff0c;主要用于Java项目&#xff0c;它由Apache软件基金会维护。Maven能够自动化完成编译、测试、打包、发布等构建过程&#xff0c;可以大大提高开发效率&#xff0c;保证项目的质量。 下面我们从几个方面来介绍一下MAVEN的功能…

《人生苦短,我用python·四》pybind11多场景使用

引言 Pybind11作为一个强大的工具&#xff0c;不仅可以轻松地将简单的C函数和类暴露给Python&#xff0c;还可以处理更复杂的场景&#xff0c;比如支持C标准库容器、处理C异常、以及自定义数据结构的转换。本文将深入介绍Pybind11的一些高级用法&#xff0c;帮助你在实际项目中…

为什么用excel求出的和是错误的?

Excel中求和结果错误的原因可能有几种常见的情况&#xff1a;1. **数据格式问题**&#xff1a;有时候数字可能被错误地视为文本格式。这种情况下&#xff0c;Excel 在求和时会忽略这些单元格。你可以通过将这些单元格的格式改为数值格式来解决。2. **隐藏的行或列**&#xff1a…

SpringBoot前后端传递数据时常用的JSON格式数据是什么?【讲解JSON概念、语法、以及Java对象互转】

SpringBoot前后端传递数据时常用的JSON格式数据是什么&#xff1f; JSON概念JSON语法JSON的两种结构&#xff1a;JSON字符串和Java对象互转&#xff1a;objectMapper.writeValueAsString(person);objectMapper.readValue(jsonStr,Person.class); 在SpringMVC框架中&#xff0c;…

Go 语言学习笔记之数组与切片

大家好&#xff0c;我是码农先森。 数组与切片的区别 在 Go 语言中&#xff0c;数组和切片是两种不同的数据结构&#xff0c;它们之间有以下主要区别。 参数长度&#xff1a; 数组&#xff08;Array&#xff09;&#xff1a;数组的长度是固定的&#xff0c;在创建时就需要指…

Python爬虫技术:动态JavaScript加载音频的解析

在当今的互联网世界中&#xff0c;JavaScript已成为构建丰富交互体验不可或缺的技术。然而&#xff0c;对于网络爬虫开发者来说&#xff0c;JavaScript动态生成的内容却带来了不小的挑战。音频内容的动态加载尤其如此&#xff0c;因为它们往往涉及到复杂的用户交互和异步数据加…

vscode配置vue格式化代码不管用

所有配置都配好了就是无法使用自己想要的vetur格式化代码 后台发现调整默认格式化代码的顺序就可以&#xff0c; 修改该后就可以了

java课程设计GUI学生信息管理系统

目录 系统内容.. 3 用户界面模块... 4 数据存储模块... 4 信息管理模块... 4 管理模块.. 4 主要模块的算法描述... 4 –简要的语言描述... 4 运行及调试分析&#xff08;测试数据及测试结果&#xff09;.. 5 课程设计总结... 7 参考文献&#xff08;至少三个&#xf…

分类判决界面---位势函数法

本篇文章是博主在人工智能等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学习笔记&#…

SD卡无法读取的解决之道与预防措施

一、SD卡无法读取的现象描述 在数字化时代&#xff0c;SD卡已成为我们生活中不可或缺的数据存储设备&#xff0c;它广泛应用于数码相机、手机、平板等设备中。然而&#xff0c;当我们试图读取SD卡时&#xff0c;有时会遇到无法识别或无法访问的情况&#xff0c;这就是我们所说…

基于matlab的不同边缘检测算子的边缘检测

1 原理 1.1 边缘检测概述 边缘检测是图像处理和计算机视觉中的基本问题&#xff0c;其目的在于标识数字图像中亮度变化明显的点。这些变化通常反映了图像属性的重要事件和变化&#xff0c;如深度不连续、表面方向不连续、物质属性变化和场景照明变化等。边缘检测在特征提取中…

36.Http协议的设计与解析

Http协议比Redis协议复杂的多,如果程序员自己去实现,工作量大。 Netty已经把Http协议的编解码器实现好了,只需要简单的配置就可以使用。 做一个http的服务端需要HttpServerCodec。 看它继承的父类: 结合了两个类: HttpRequestDecoder(入站处理器extends Channelnbound…

微信小程序反编译 2024 unveilr.exe

ps&#xff1a;一开始用的反编译工具是wxappUnpacker&#xff0c;后面改为 unveilr.exe 1.先找到小程序安装目录“E:\聊天记录\WeChat Files\Applet”&#xff0c;要反编译小程序的包 文件夹下的名字对应的是小程序ID&#xff0c;如果不确定是哪个&#xff0c;可以删除->打…

使用SpringBootTest测试项目

当我们开发项目后&#xff0c;通常需要进行单元测试&#xff0c;确保开发符合预期。但是对于Springboot项目&#xff0c;依赖部分IOC容器对象的注入。比如代码中存在Autowired、Service、Mapper等。 1、确保pom.xml中包含了依赖&#xff0c;其中的version和scope&#xff0c;大…

流程控制相关

1.break语句 只能用在循环体内&#xff0c;用来结束当前循环 语法&#xff1a; while 循环条件表达式&#xff1a; 语句块 if 条件表达式&#xff1a; break 语句块 for i in 迭代对象&#xff1a; 语句块 if 条件表达式&#xff1a; break 语句块 小练&#xff1a; 求一…

52、U-boot2023的移植教程

uboot&#xff1a;https://ftp.denx.de/pub/u-boot/ nxp-uboot&#xff1a;https://github.com/nxp-imx/uboot-imx 1、顶层Makefile 文件加入编译的两种方式&#xff1a;以xxx/xxx.c文件为例 1、使用menuconfig: 先编辑.c所在目录下的Kconfig&#xff0…