(Java)动规_数字三角形、动规_数字三角形的递推和优化、动规_最佳加法表达式、动规_最长公共子序列、动规_最长上升子序列、动规_滑雪、动规ex_HelpJimmy

package 蓝桥杯;

import java.util.Scanner;

public class VO动规_数字三角形 {

	static int n;
	static int[][] a=new int[101][101]; 
	static int[][] MaxSum=new  int[101][101];
	public static void main(String[] args) {

		Scanner reader=new Scanner(System.in);
		int n=reader.nextInt();
		 
		for(int i=1;i<=n;i++)
			for(int j=1;j<=i;j++) {
				a[i][j]=reader.nextInt();
				MaxSum[i][j]=-1;
			}
		System.out.println(maxSum(1,1));
	}
	
	static int maxSum(int i,int j) {
		if(MaxSum[i][j]!=-1)
			return MaxSum[i][j];
		if(i==n)
			MaxSum[i][j]=a[i][j];
		else {
			int x=maxSum(i+1, j);
			int y=maxSum(i+1, j+1);
			MaxSum[i][j]=Math.max(x, y)+a[i][j];
		}
		return MaxSum[i][j];
	}

}

package 蓝桥杯;

import java.util.Scanner;
//由递归转化为递推
//空间优化:MaxSum数组可以不要,直接用a的第n行替代MaxSum即可。节省空间,时间复杂度不变
public class VO动规_数字三角形的递推和优化 {

	static int n;
	static int[][] a=new int[101][101]; 
	static int[] MaxSum;
	public static void main(String[] args) {

		Scanner reader=new Scanner(System.in);
		int n=reader.nextInt();
		for(int i=1;i<=n;i++)
			for(int j=1;j<=i;j++)
				a[i][j]=reader.nextInt();
		MaxSum=a[n];//MaxSum指向第n行
		for(int i=n-1;i>=1;i--)
			for(int j=1;j<=i;j++)
				MaxSum[j]=Math.max(MaxSum[j], MaxSum[j+1])+a[i][j];
		System.out.println(MaxSum[1]);
	}
	


}

package 蓝桥杯;

import java.util.Arrays;
import java.util.Scanner;
/*
有不超过15组数据 
每组数据两行。第一行是整数m,表示有m个加号要放( 0<=m<=50) 
第二行是若干个数字。数字总数n不超过50,且 m <= n-1
输入:
2
123456
1
123456
4
12345
输出:
102
579
15
*/
public class VO动规_最佳加法表达式 {
	
	//最大数为ox3f3f3f3f
	static int n,m;
	static String numberstring;
	static int[] a=new int[1005];//存输入的数字传
	static int[][] num=new int[1005][1005];//预存从第1位到第n位的所有可能拼凑出的值
	static int[][] dp=new int[1005][1005];//dp[m][n]在n位数字之间添加m个加号所能形成的表达式的最小值。
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		while(reader.hasNext()) {
		m=reader.nextInt();//加号的数量
		numberstring = reader.next();
		n=numberstring.length();//1-9的数字的个数
		for(int i=1;i<=n;i++)
			a[i]=numberstring.charAt(i-1)-'0';
		//预处理,计算i位到j位拼凑出的数字
		for(int i=1;i<=n;i++) {
			num[i][i]=a[i];//i和j在同一个位置,也就是只有一个数字的情况
			for(int j=i+1;j<=n;j++)
				num[i][j]=num[i][j-1]*10+a[j];
		}
		//将dp数组中的所有值,初始化为无穷大
		for(int i=0;i<=m;i++)
		Arrays.fill(dp[i],0x3f3f3f3f);//这个方法类似与c里面的memeset,注意括号中的第一个参数只能放一维数组
		for(int j=1;j<=n;j++)
			dp[0][j]=num[1][j];//临界条件,无加号时的情况。
		//递推式
		for(int i=1;i<=m;i++)
			for(int j=i;j<=n;j++)
				for(int k=i;k<=j;k++)
					dp[i][j]=Math.min(dp[i][j], dp[i-1][k]+num[k+1][j]);
		System.out.println(dp[m][n]);
		}
	}

}

package 蓝桥杯;

import java.util.Scanner;

public class VO动规_最长公共子序列 {

	public static void main(String[] args) {

		int[][] maxlen;
		Scanner reader=new Scanner(System.in);
		while(reader.hasNext()) {
		String str1=reader.next();
		String str2=reader.next();
		int length1=str1.length();
		int length2=str2.length();
		maxlen=new int[length1+1][length2+1];
		for(int i=0;i<=length1;i++)
			maxlen[i][0]=0;
		for(int j=0;j<=length2;j++)
			maxlen[0][j]=0;
		for(int i=1;i<=length1;i++)
			for(int j=1;j<=length2;j++)
				if(str1.charAt(i-1)==str2.charAt(j-1))
					maxlen[i][j]=maxlen[i-1][j-1]+1;
				else 
					maxlen[i][j]=Math.max(maxlen[i][j-1], maxlen[i-1][j]);
		System.out.println(maxlen[length1][length2]);
		}
	}

}

package 蓝桥杯;

import java.util.Arrays;
import java.util.Scanner;

public class VO动规_最长上升子序列 {

	public static void main(String[] args) {

		Scanner reader=new Scanner(System.in);
		int n=reader.nextInt();
		int[] a=new int[n+1],maxlen=new int[n+1];
		for(int i=1;i<=n;i++){
			a[i]=reader.nextInt();
			maxlen[i]=1;
		}
		for(int i=2;i<=n;i++)//每次求以第i个数为终点的最长上升子序列的长度
			for(int j=1;j<i;j++)//查看以第j个数为重点的最长上升子序列
				if(a[i]>a[j])
					maxlen[i]=Math.max(maxlen[i], maxlen[j]+1);
		Arrays.sort(maxlen);//求一个数组中最大值
		System.out.println(maxlen[n]);
	}

}

package 蓝桥杯;

import java.util.Scanner;import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;

public class VO动规_滑雪 {

	static int[][] Hight;//滑雪场的高度
	static int[][] Lenght;//各个点可滑的最长距离
	static int row,col;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner reader=new Scanner(System.in);
		row=reader.nextInt();//行数
		col=reader.nextInt();
		Hight=new int[row][col];
		Lenght=new int[row][col];
		for(int i=0;i<row;i++)
			for(int j=0;j<col;j++) {
				Hight[i][j]=reader.nextInt();
//				Lenght[i][j]=1;
			}
		int Max=0;
		for(int i=0;i<row;i++)
			for(int j=0;j<col;j++) {
				int temp=find(i,j,Integer.MAX_VALUE);
				if(temp>Max) Max=temp;
			}
		System.out.println(Max);
	}
	static int find(int i,int j,int value) {
		if(i<0||j<0||i>=row||j>=col||value<=Hight[i][j])
			return 0;
		if(Lenght[i][j]>0)
			return Lenght[i][j];
		int up=find(i-1, j,Hight[i][j]);
		int down=find(i+1, j,Hight[i][j]);
		int left=find(i, j-1,Hight[i][j]);
		int right=find(i, j+1,Hight[i][j]);
		Lenght[i][j]=my_max(up,down,left,right)+1;
		return Lenght[i][j];
	}
	static int my_max(int a,int b,int c,int d) {
		return Math.max(Math.max(a, b), Math.max(c, d));
	}

}

package 蓝桥杯;


import java.util.Scanner;


public class VO动规ex_HelpJ {


public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();//测试数据的组数
int S=0;
while(t>0)
{
int N=sc.nextInt();//平台的数目
int X=sc.nextInt();
int Y=sc.nextInt();//Jimmy开始下落的位置的横竖坐标
int MAX=sc.nextInt();//一次下落的最大高度
int[] X1=new int[N];//第i个平台的左端点
int[] X2=new int[N];//第i个平台的右端点
int[] H=new int[N];//第i个平台的高度
for(int i=0;i<N;i++)
{
X1[i]=sc.nextInt();
X2[i]=sc.nextInt();
H[i]=sc.nextInt();
}
//d[i][0]代表从第i个平台左边为起点下落的最小时间
//d[i][1]代表从第i个平台右边为起点下落的最小时间
int[][] d=new int[N][2];

//对N个平台按高度进行冒泡排序,平台由低到高存储在数组中
for(int i=0;i<N-1;i++)
{
for(int j=0;j<N-1-i;j++)
{
if(H[j]>H[j+1])
{
int temp;
temp=H[j];
H[j]=H[j+1];
H[j+1]=temp;
temp=X1[j];
X1[j]=X1[j+1];
X1[j+1]=temp;
temp=X2[j];
X2[j]=X2[j+1];
X2[j+1]=temp;//交换平台的所有信息
}
}
}
d[0][0]=H[0];
d[0][1]=H[0];//第0个平台左边(右边)为起点下落的最小时间
for(int i=1;i<N;i++)
{
int k=i-1;//左边走
while(k>=0&&H[i]-H[k]<=MAX)
{
//如果平台i的左边有平面且两者高度不超过MAX
if(X1[i]>=X1[k]&&X1[i]<=X2[k])//平台i的左端点在平台k之间
//高度差+(下一个平台往左走的距离+下一个平台往左落下)(或往右)的最小时间
{
d[i][0]=H[i]-H[k]+min(X1[i]-X1[k]+d[k][0],X2[k]-X1[i]+d[k][1]);
break;//找到了这个平台就不需要再往下找了
}
k--;//如果在这个高度没有找到平台继续往下找
}
//平面i左边没有平台了,到地面了,看高度是否超过了MAX
if(k!=-1&&H[i]-H[k]>MAX)
{
d[i][0]=999999;//Jimmy会摔死
}
if(k==-1)
{
if(H[i]<=MAX)
d[i][0]=H[i];
}
if(k==-1&&H[i]>MAX)
{
d[i][0]=999999;//Jimmy会摔死
}


int p=i-1;//右边走
while(p>=0&&H[i]-H[p]<=MAX)
{
//如果平台i的右边有平面且两者高度不超过MAX
if(X2[i]>=X1[p]&&X2[i]<=X2[p])//平台i的右端点在平台k之间
//高度差+(下一个平台往左走的距离+下一个平台往左落下)(或往右)的最小时间
{
d[i][1]=H[i]-H[p]+min(X2[i]-X1[p]+d[p][0],X2[p]-X2[i]+d[p][1]);
break;//找到了这个平台就不需要再往下找了
}
p--;
}
//平面i右边没有平台了,到地面了,看高度是否超过了MAX
if(p!=-1&&H[i]-H[p]>MAX)
{
d[i][1]=999999;//会摔死
}
if(p==-1)
{
if(H[i]<=MAX)
d[i][1]=H[i];
}
if(p==-1&&H[i]>MAX)
{
d[i][1]=999999;//会摔死
}
}


//Jimmy从高于所有平台的(X,Y)处往下落
int q=N-1;
while(q>=0)
{
if(X>=X1[q]&&X<=X2[q])//由高往低查看,因为最先落在高的地方
{
S=min(Y-H[q]+X-X1[q]+d[q][0],Y-H[q]+X2[q]-X+d[q][1]);

break;
}
q--;
}
if(q==-1)//Jimmy不能落到所有的平台上
{
S=Y;
}
System.out.println(S);
t--;
}//测试组数

}


public static int min(int a,int b){
if(a<b)
return a;
else
return b;
}
}


发布了20 篇原创文章 · 获赞 1 · 访问量 409

猜你喜欢

转载自blog.csdn.net/XMY_UPUPUP/article/details/104723971