一、蓝桥杯省赛——数字三角形
(1)题目描述
上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右 边的那个数。此外,向左下走的次数与向右下走的次数相差不能超过 1。
输入描述
输入的第一行包含一个整数 N\ (1 \leq N \leq 100)N (1≤N≤100),表示三角形的行数。
下面的 NN 行给出数字三角形。数字三角形上的数都是 0 至 100 之间的整数。
输出描述
输出一个整数,表示答案。
(2)代码实现
import java.util.*;
public class main{
static Scanner in=new Scanner(System.in);
static final int N=110;
static int[][] a=new int[N][N];
static int[][] f=new int[N][N];
public static void main(String args[])
{
int n=in.nextInt();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
a[i][j]=in.nextInt();
}
}
f[1][1]=a[1][1];
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
f[i][j]=Math.max(f[i-1][j]+a[i][j],f[i-1][j-1]+a[i][j]);
}
}
if(n%1!=0)
{
System.out.println(f[n][n/2+1]);
}else{
System.out.println(Math.max(f[n][n/2+1],f[n][n/2]));
}
}
}
二、ACWing:895. 最长上升子序列
(1)题目描述
给定一个长度为 NN 的数列,求数值严格单调递增的子序列的长度最长是多少。
输入格式
第一行包含整数 NN。
第二行包含 NN 个整数,表示完整序列。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤10001≤N≤1000,
−109≤数列中的数≤109−109≤数列中的数≤109
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
(2)代码实现
import java.util.*;
public class Main
{
static Scanner in=new Scanner(System.in);
static int N=1010;
static int a[]=new int[N],f[]=new int[N];
public static void main(String args[])
{
int n=in.nextInt();
for(int i=1;i<=n;i++) a[i]=in.nextInt();
int max=0;
for(int i=1;i<=n;i++)
{
f[i]=1;//赋值
for(int j=1;j<i;j++)
{
if(a[j]<a[i]) f[i]=Math.max(f[i],f[j]+1);//状态转移方程
}
max=Math.max(max,f[i]);
}
System.out.println(max);
}
}
三、ACWing:896. 最长上升子序列 II
(1)题目描述
给定一个长度为 NN 的数列,求数值严格单调递增的子序列的长度最长是多少。
输入格式
第一行包含整数 NN。
第二行包含 NN 个整数,表示完整序列。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N≤1000001≤N≤100000,
−109≤数列中的数≤109−109≤数列中的数≤109
输入样例:
7
3 1 2 1 8 5 6
输出样例:
4
(2)代码实现
import java.util.*;
import java.io.*;
public class Main
{
static int N=100010;
static Scanner in=new Scanner(System.in);
static int[] a=new int[N];
static int[] q=new int[N];
public static void main(String[] args)
{
int n=in.nextInt();
for(int i=1;i<=n;i++) a[i]=in.nextInt();
int len=0;
q[0]=-0x3f3f3f3f; //0x3f3f3f3f代表无穷大 我们这里取反
for(int i=1;i<=n;i++)
{
int l=0,r=len;
while(l<r){
int mid=(l+r+1)>>1; //因为l=mid 所以我们这里需要向上取整
if(q[mid]<a[i]) l=mid;
else r=mid-1;
}
len=Math.max(len,r+1);
q[r+1]=a[i];
}
System.out.println(len);
}
}
四、ACWing:897. 最长公共子序列
(1)问题描述
给定两个长度分别为 NN 和 MM 的字符串 AA 和 BB,求既是 AA 的子序列又是 BB 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 NN 和 MM。
第二行包含一个长度为 NN 的字符串,表示字符串 AA。
第三行包含一个长度为 MM 的字符串,表示字符串 BB。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤10001≤N,M≤1000
输入样例:
4 5
acbd
abedc
输出样例:
3
(2)代码实现
import java.util.*;
public class Main
{
static Scanner in=new Scanner(System.in);
static int f[][]=new int[1010][1010];
public static void main(String args[])
{
int n=in.nextInt();
int m=in.nextInt();
String s1=" "+in.next();
String s2=" "+in.next();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(s1.charAt(i)==s2.charAt(j))
f[i][j]=Math.max(f[i][j],f[i-1][j-1]+1);
else
f[i][j]=Math.max(f[i-1][j-1],Math.max(f[i-1][j],f[i][j-1]));
}
}
System.out.println(f[n][m]);
}
}
五、ACWing:902. 最短编辑距离
(1)问题描述
给定两个字符串 AA 和 BB,现在要将 AA 经过若干操作变为 BB,可进行的操作有:
- 删除–将字符串 AA 中的某个字符删除。
- 插入–在字符串 AA 的某个位置插入某个字符。
- 替换–将字符串 AA 中的某个字符替换为另一个字符。
现在请你求出,将 AA 变为 BB 至少需要进行多少次操作。
输入格式
第一行包含整数 nn,表示字符串 AA 的长度。
第二行包含一个长度为 nn 的字符串 AA。
第三行包含整数 mm,表示字符串 BB 的长度。
第四行包含一个长度为 mm 的字符串 BB。
字符串中均只包含大写字母。
输出格式
输出一个整数,表示最少操作次数。
数据范围
1≤n,m≤10001≤n,m≤1000
输入样例:
10
AGTCTGACGC
11
AGTAAGTAGGC
输出样例:
4
(2)代码实现
import java.util.*;
public class Main
{
static Scanner in=new Scanner(System.in);
static int N=1010;
static char a[]=new char[N],b[]=new char[N];
static int f[][]=new int[N][N];
public static void main(String args[])
{
int n=in.nextInt();
System.arraycopy(in.next().toCharArray(),0,a,1,n);
int m=in.nextInt();
System.arraycopy(in.next().toCharArray(),0,b,1,m);
for(int i=0;i<=m;i++) f[0][i]=i;
for(int j=0;j<=n;j++) f[j][0]=j;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
f[i][j]=Math.min(f[i-1][j]+1,f[i][j-1]+1);
if(a[i]==b[j]) f[i][j]=Math.min(f[i][j],f[i-1][j-1]);
else f[i][j]=Math.min(f[i][j],f[i-1][j-1]+1);
}
System.out.println(f[n][m]);
}
}