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

动态规划-数字三角形(模板)、迪沃斯定理(模板)、翻转后1的数量(2星)、最长公共子序列、最长上升子序列

数字三角形(模板)

数字三角形

题目描述

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和(路径上的每一步只可沿左斜线向下或右斜线向下走)。

输入描述

输入的第一行包含一个整数 N (1≤N≤100)N (1≤N≤100),表示三角形的行数。

下面的 NN 行给出数字三角形。数字三角形上的数都是 00 至 9999 之间的整数。

输出描述

输出一个整数,表示答案。

输入输出样例

示例

输入

5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5

输出

30
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=110; static int a[][]=new int[N][N]; static int f[][]=new int[N][N]; static int n; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); n=Integer.parseInt(st.nextToken()); for (int i = 1; i <= n; i++) { st=new StringTokenizer(br.readLine()); for (int j = 1; j <= i; j++) { a[i][j]=Integer.parseInt(st.nextToken()); } } //f(i,j)表示到顶点(i,j)的最大的和 for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { f[i][j]=a[i][j]+Math.max(f[i-1][j], f[i-1][j-1]); } } int res=Integer.MIN_VALUE; for (int i = 1; i <= n; i++) { res=Math.max(res, f[n][i]); } bw.write(res+""); br.close(); bw.flush(); bw.close(); } }

迪沃斯定理(模板)

问题描述

给定一个长度为 nn 的序列 aa,你需要输出如下内容:

第一行输出该序列最长严格上升子序列的长度。

第二行输出该序列最少的严格上升子序列的划分个数。

第三行输出该序列最长非严格上升子序列的长度。

第四行输出该序列最少的非严格上升子序列的划分个数。

严格上升:对于 i<j,ai<aji<j,ai​<aj​。

非严格上升:对于 i<j,ai≤aji<j,ai​≤aj​。

最少的严格上升子序列的划分个数:对于一个子序列,其最少可以划分成几个严格上升子序列。例如 [3,1,2,2,3][3,1,2,2,3],我们最少可以划分成 [3],[1,2],[2,3][3],[1,2],[2,3]。

输入格式

第一行输入一个正整数 nn。(1≤n≤1000)(1≤n≤1000)

第二行输入 nn 个整数,表示序列 aa。(1≤ai≤100,1≤i≤n)(1≤ai​≤100,1≤i≤n)

输出格式

第一行输出该序列最长严格上升子序列的长度。

第二行输出该序列最少的严格上升子序列的划分个数。

第三行输出该序列最长非严格上升子序列的长度。

第四行输出该序列最少的非严格上升子序列的划分个数。

样例输入

10 1 4 7 3 6 8 1 3 4 4

样例输出

4 4 5 3

提示

根据迪沃斯定理:

最长严格上升子序列最少划分数 = 最长非严格下降子序列的长度。

最长非严格上升子序列的最少划分数 = 最长严格下降子序列的长度。

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=1010; static int a[]=new int[N]; static int f[]; static int n; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); n=Integer.parseInt(st.nextToken()); st=new StringTokenizer(br.readLine()); for (int i = 1; i <= n; i++) { a[i]=Integer.parseInt(st.nextToken()); } //f(i)表示以i结尾的最长严格上升子序列的长度 f=new int[n+1]; for (int i = 1; i <= n; i++) { f[i]=1; for (int j = i-1; j > 0; j--) { if(a[j]<a[i]){ f[i]=Math.max(f[i], f[j]+1); } } } int r1=1; for (int i = 1; i <= n; i++) { r1=Math.max(r1, f[i]); } bw.write(r1+"\n"); //f(i)表示以i结尾的最长不严格下降子序列的长度 f=new int[n+1]; for (int i = 1; i <= n; i++) { f[i]=1; for (int j = i-1; j > 0; j--) { if(a[j]>=a[i]){ f[i]=Math.max(f[i], f[j]+1); } } } int r2=1; for (int i = 1; i <= n; i++) { r2=Math.max(r2, f[i]); } bw.write(r2+"\n"); //f(i)表示以i结尾的最长不严格上升子序列的长度 f=new int[n+1]; for (int i = 1; i <= n; i++) { f[i]=1; for (int j = i-1; j > 0; j--) { if(a[j]<=a[i]){ f[i]=Math.max(f[i], f[j]+1); } } } int r3=1; for (int i = 1; i <= n; i++) { r3=Math.max(r3, f[i]); } bw.write(r3+"\n"); //f(i)表示以i结尾的最长严格下降子序列的长度 f=new int[n+1]; for (int i = 1; i <= n; i++) { f[i]=1; for (int j = i-1; j > 0; j--) { if(a[j]>a[i]){ f[i]=Math.max(f[i], f[j]+1); } } } int r4=1; for (int i = 1; i <= n; i++) { r4=Math.max(r4, f[i]); } bw.write(r4+"\n"); br.close(); bw.flush(); bw.close(); } }

翻转后1的数量(2星)

问题描述

现在有一个 00 和 11 构成的长度为 nn 的子符串 SS,你可以对 SS 串进行至多一次操作,操作具体为选择 SS 串中的一个区间,将该区间所有的字符翻转,问在经过至多一次操作后 SS 串中 11 的数量最多可以为多少?

翻转:0→1,1→00→1,1→0。

输入格式

第一行输入一个正整数 nn,表示字符串的长度。

第二行输入长度为 nn 的字符串 SS。

输出格式

输出一个整数,表示 11 的数量最大值。

样例输入

5 00101

样例输出

4

说明

选择区间 [1,2][1,2] 进行翻转,SS 串成为11101,有 44 个 11。

评测数据规模

1≤n≤1051≤n≤105。

import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=100010; static int f[][]=new int[N][3]; static int n; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); n=Integer.parseInt(st.nextToken()); char s[]=(" "+br.readLine()).toCharArray(); //我们定义状态f(i,0)为到当前i为止时未经过翻转的一的最大数量 //我们定义状态f(i,1)为到当前i为止时正要翻转的一的最大数量 //我们定义状态f(i,2)为到当前i位置时停止翻转的一的最大数量 //f(i,0)=f(i-1,0)+x-'0' //f(i,1)=max(f(i-1,0),f(i-1,1))+(x^1)-'0' ^表示异或 (x^1)可以讲当前位置取反 这里是ASCII码的取反 //f(i,2)=max(f(i-1,1),f(i-1,2))+x-'0' //该位置不能是0 for (int i = 1; i <= n; i++) { char x=s[i]; f[i][0]=f[i-1][0]+(x-'0'); f[i][1]=Math.max(f[i-1][0], f[i-1][1])+((x^1)-'0'); if(i!=1)f[i][2]=Math.max(f[i-1][1], f[i-1][2])+(x-'0'); } int res=Math.max(Math.max(f[n][0], f[n][1]),f[n][2]); bw.write(res+""); br.close(); bw.flush(); bw.close(); } }

最长公共子序列

题目描述

给定一个长度为 NN 数组 aa 和一个长度为 MM 的数组 bb。

请你求出它们的最长公共子序列长度为多少。

输入描述

输入第一行包含两个整数 N,MN,M,分别表示数组 aa 和 bb 的长度。

第二行包含 NN 个整数 a1,a2,...,ana1​,a2​,...,an​。

第三行包含 MM 个整数 b1,b2,...,bnb1​,b2​,...,bn​。

1≤N,M≤1031≤N,M≤103,1≤ai,bi≤1091≤ai​,bi​≤109。

输出描述

输出一行整数表示答案。

输入输出样例

示例 1

输入

5 6 1 2 3 4 5 2 3 2 1 4 5

输出

4

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=1010; static int a[]=new int[N]; static int b[]=new int[N]; static int f[][]=new int[N][N]; static int n; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); n=Integer.parseInt(st.nextToken()); int m=Integer.parseInt(st.nextToken()); st=new StringTokenizer(br.readLine()); for (int i = 1; i <= n; i++) { a[i]=Integer.parseInt(st.nextToken()); } st=new StringTokenizer(br.readLine()); for (int i = 1; i <= m; i++) { b[i]=Integer.parseInt(st.nextToken()); } //f[i][j]定义为以a中i下标结尾 b中j下标结尾 的 最长公共子序列长度 for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { if(a[i]==b[j])f[i][j]=f[i-1][j-1]+1; else f[i][j]=Math.max(f[i][j-1],f[i-1][j]); } } bw.write(f[n][m]+""); br.close(); bw.flush(); bw.close(); } }

最长上升子序列

给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。

输入格式

第一行包含整数 N。

第二行包含 N 个整数,表示完整序列。

输出格式

输出一个整数,表示最大长度。

数据范围

1≤N≤100000,
−109≤数列中的数≤109

输入样例:
7 3 1 2 1 8 5 6
输出样例:
4
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.*; public class Main { static int N=100010; static int a[]=new int[N]; static int f[]=new int[N]; static int n; static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); public static void main(String[] args) throws IOException { StringTokenizer st=new StringTokenizer(br.readLine()); n=Integer.parseInt(st.nextToken()); st=new StringTokenizer(br.readLine()); for (int i = 1; i <= n; i++) { a[i]=Integer.parseInt(st.nextToken()); } //定义f[i]为长度为i的严格单调递增的子序列末尾最小的数 //定义为最小的数 是因为相等于是贪心策略 为后续更长的子序列做基础 //依次加进去的数保持单调递增 若当前的数小于f最后一个元素,则在f中找到第一个大于等于我的数将其替换 //最后f的长度就是答案 int len=0;//f的长度 for (int i = 1; i <= n; i++) { if(len==0 || f[len-1]<a[i])f[len++]=a[i]; else{ int idx=findMax(a[i],len-1); f[idx]=a[i]; } } // for (int i = 1; i <= n; i++) { // bw.write(f[i]+" "); // } // bw.write("\n"); bw.write(len+""); br.close(); bw.flush(); bw.close(); } static int findMax(int u,int n){ int l=0,r=n; while(l<r){ int mid=(l+r)>>1; if(f[mid]>=u)r=mid; else l=mid+1; } return l; } }
http://www.jsqmd.com/news/1170390/

相关文章:

  • 2026年7月最新深圳雅典官方售后客户服务热线与维修网点地址汇总 - 亨得利官方服务中心
  • Harness Engineering:AI系统编排工程与递归自改进技术解析
  • 【新手搭建】 OpenClaw v2.7.9 详解 Windows11 路径与权限配置(含安装包)
  • 技术团队管理的工程化方法:从1on1到绩效评估到成长路径的系统化实践
  • 英雄联盟玩家的智能副驾驶:如何用League Akari让你的游戏体验提升300%
  • 2026年Agent工程化落地,必须避开的5大核心误区:生产级智能体部署的深度技术前瞻
  • 10家口碑优质GEO优化公司推荐,2026头部正规靠谱GEO服务商排行榜+避坑FAQ - GEO优化
  • DeepSeek代码补全响应延迟骤降73%的3个冷门配置,GitHub Star破20k团队内部流出
  • Claude Code智能编程实战手册(从安装到生产级落地全链路)
  • 龍魂·感官教育尊严三位一体协议 v1.0
  • G6D-ASI继电器与R7FA4M3AF3CFB144微控制器的直流负载管理优化方案
  • MQTT QoS 0/1/2 消息可靠性实测:Python+paho-mqtt 3种场景代码对比
  • IT疑难杂症诊疗室:根治系统故障全攻略
  • IDC预测2031年中国将有3.5亿个智能体,企业该怎么布局?——企业级AI Agent工程化落地与选型指南
  • 2026年成都留学机构推荐榜:五家优选通过率深度解析 - 科技焦点
  • Ansys Fluent 混合流动仿真:从2D简化到3D圆管的5步网格与结果差异分析
  • 2026年7月最新浪琴北京朝阳大悦城维修保养服务电话 - 浪琴官方售后服务中心
  • 寄电瓶车带电池多少钱?2026避坑指南看这篇就够 - 快递物流资讯
  • LX Music Desktop:免费开源跨平台音乐播放器终极指南
  • CVE-2026-48282 ColdFusion漏洞实战排查与修复全教程|KEV高危漏洞企业落地SOP
  • 为什么换同义词降不了 AI 率?真正要改的是这个 - 我要发一区
  • 小游戏定制开发:告别同质化,小众团队的“深潜”与机遇
  • URP中Matcap Shader实战:原理、实现与性能优化指南
  • 如何用免费调试工具深度探索《艾尔登法环》:褪色者的终极冒险指南
  • STM32与ISOM8710实现高压安全隔离的设计与实践
  • 超便携墨水屏硬件设计实战:从选型到低功耗优化
  • Unity大文件下载:基于UnityWebRequest实现高效断点续传方案
  • iPaaS概念原理(2)| iPaaS的架构模型是怎样的?
  • 2026 新都黄金回收完整实测攻略!大丰 / 桂湖 / 斑竹园 / 石板滩正规门店对比,避开扣重压价套路 - 福金阁黄金回收
  • 临沂企业为什么开始使用AI数字人?客服、导览、营销三大场景解析