蓝桥杯练习题2

动态规划

++动态规划三大题型:计数问题、最值问题、存在性问题;++

【最小权值】-- 最值问题
【题目分析】

import java.util.Arrays;

Arrays类中的一个方法:Arrays.fill(int[] m,int n)

//给 int 类型(或者char类型/Long类型...)的数组全部空间填充上数字 n ;

Arrays.fill(int[] m,int start_index,int end_index,int n)

//在数组 m 的 start_index(包含该起始索引,可以取0)到 end_index(不包含该索引,最大到m.length) 填充数字n ;

java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //从0-2021
        long[] dp = new long[2022];
        //dp储存的是不同结点数量时的最小权值
        Arrays.fill(dp,-1);
        
        //空子树权值是0 无根节点
        dp[0] = 0;
        //dp[1]是有一个结点(根结点)的最小权值
        dp[1] = 1;
        
        //i是该树所有结点的个数
        //i从2到2021
        for(int i=2;i<dp.length;i++){
          long min = Long.MAX_VALUE;
          //j=left 是该树左结点的个数
          //i-j-1=right 是该树的右结点
          for(int j=0;j<i;j++){
            int left = j;
            int right = i - j - 1;  //1是根节点
            long temp = 1 + 2*dp[left] + 3*dp[right] + left*left*right;
            min = Math.min(min,temp);
          }
          dp[i] = min;
        }
        System.out.println(dp[2021]);
        scan.close();
    }
}
【砝码称重】-- 计数问题
java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int num = 0;//代表重量的种类
        //题目有提示N的范围[1,100] 总重量不超过100000
        int N = scan.nextInt();
        int[] w = new int[101];  //使用w[1]到w[100]
        //默认全是false;
        boolean[][] dp = new boolean[101][100001];   //使用[1...100]和[1...100000]  
        
        long weight = 0L;
        for(int i = 1;i< N+1;i++){
          //初始化w[1]到w[N]
          w[i] = scan.nextInt();
          weight+=w[i];//所有情况中最大的砝码重量
        }
        
        /*核心代码*/
        //放第i个砝码 i=1...N
        for(int i=1;i<N+1;i++){
          for(int j=1;j<=weight;j++){
            if(j==w[i]){
              dp[i][j] = true;  //能够称出的重量赋T;
              //dp[0][1...max]在初始化的时候默认是F;
            }else{
              //设定放左边总重量减少 右边总重量增加
              //前 i 个砝码可以不可以称出 j ?考虑以下情况
              //1.如果dp[i-1][j]=T;上一个砝码已经可以称出 j 这个重量; 第 i 个砝码不放了;
              //2.dp[i-1][abs(j-w[i])];上一个砝码(前i-1个)已经可以称出 j-w[i] ,那么第i个砝码(放右边)就可以称出 j 重量。dp[i][j]=T; 
              //3.dp[i-1][j+w[i]];上一个砝码(前i-1个)已经可以称出 j+w[i],那么第i个砝码(放左边)就可以称出 j 重量,dp[i][j]=T; 
              dp[i][j] = dp[i-1][j] || dp[i-1][Math.abs(j-w[i])] || dp[i-1][j+w[i]];
            }
          }
        }
        for(int i=1;i<=weight;i++){
          if(dp[N][i]){
            num++;
          }
        }
        System.out.println(num);
        scan.close();
    }
}
【序列】
java 复制代码
package test;

import java.math.BigInteger;
import java.util.HashSet;
import java.util.Scanner;
import java.util.*;
import java.lang.*;

public class test2 {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int N = scan.nextInt();
		int[] a = new int[N];
		int[] b = new int[N];
		int[] S = new int[N + 1];
		int sum = 0;
		for (int m : a) {
			m = scan.nextInt();
		}
		
		for(int i=0;i<N;i++) {
			a[i]=scan.nextInt();
		}
		int num = 0;
		
		// 首项&公差=j
		for (int j = 1; j < N + 1; j++) {
			b[0] = j;
			//初始化数组b
			for (int k = 1; k < N; k++) {
				b[k] = b[k - 1] + j;
			}
			
			for (int i = 0; i < N; i++) {
				if (b[i] % a[i] == 0) {
					num++;
				}
			}
			S[j] = num;
			num=0;
		}
		sum = 0;
		for (int i = 1; i < N + 1; i++) {
			sum += S[i];
		}
		System.out.println(sum);
		scan.close();
	}
}


【出栈次序】

n 个元素有多少种出栈顺序?

java 复制代码
public class Main {
 
	// 不用管出站后车的数量和顺序,因为进站顺序和出站顺序已经决定出站时的排序
	static int fun(int a, int b) {// a是等待进站的数目,b是站中的数目
		if (a == 0)// 此时已全部进站,出站时的顺序只有一种
			return 1;
		if (b == 0)// 此时车站为空,只能让车进站
			return fun(a - 1, 1);
		// 有两种走法:1、让一辆车进站 ;2、让一辆车出站
		return fun(a - 1, b + 1) + fun(a, b - 1);
	}
 
	static int fun(int a) {
		return fun(a, 0);
	}
 
	public static void main(String[] args) {
		System.out.println(fun(16));
	}
}

出栈顺序问题讲解 蓝桥杯_出栈序列-CSDN博客 请参考!

卡特兰数Catalan numbers

经典使用场景

1.合法的括号序列

2.二叉树形态计数

3.栈的出栈顺序

4.不同弦的相交

5.Dyck路径

6.凸多边形的三角划分

7.非交叉集合的划分

5. 卡特兰数(Catalan)公式、证明、代码、典例.-CSDN博客 参考!

java 复制代码
//函数功能: 计算Catalan的第n项
//函数参数: n为项数
//返回值:  第n个Catalan数
int Catalan(int n)
{
	if(n<=1) return 1;
	int *h = new int [n+1]; //保存临时结果
	h[0] = h[1] = 1;        //h(0)和h(1)
    //第i项Ci
	for(int i=2;i<=n;++i)    //依次计算h(2),h(3)...h(n)
	{
		h[i] = 0;
		for(int j = 0; j < i; j++) //根据递归式计算 h(i)= h(0)*h(i-1)+h(1)*h(i-2) + ... + h(i-1)h(0)
			h[i] += (h[j] * h[i-1-j]);
	}
	int result = h[n]; //保存结果
	delete [] h;       //注意释放空间
	return result;
}
【居中输出】
java 复制代码
//暴力解法

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    static int num(int m){
      int  n = 0;
      //在计算数字的位数的时候需要考虑0 否则测试用例只能通过90%
      if(m==0){
        return 1;
      }
      while(m>0){
        m/=10;
        n++;
      }
      return n;
    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int count = (10-num(n))/2;
        if(num(n)+count*2==10){
           for(int i=0;i<count;i++){
             System.out.printf("%c",'=');
           }
           System.out.printf("%d",n);
           for(int i=0;i<count;i++){
             System.out.printf("%c",'=');
           }
        }else{
           for(int i=0;i<count+1;i++){
             System.out.printf("%c",'=');
           }
           System.out.printf("%d",n);
           for(int i=0;i<count;i++){
             System.out.printf("%c",'=');
           }
        }        
        scan.close();
    }
}
【平方十位数】
java 复制代码
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
	static boolean sqrt_num1(long m) {
		// 不遗漏
		String s = m + "";
		int len = s.length();
		if (len != 10) {
			return false;
		}
		// 不重复:各个数位上的数字不重复
		int[] num = new int[10];
		for (int i = 0; i < 10; i++) {
			num[i] = 0;
		}
		while (m > 0) {
            //注意格式 (int)m%10  是把long型的数字限制在int的范围内 
            //而不是把(m%10)的结果由long转换为 int
			int last = (int) (m % 10);    
			num[last]++;
			m /= 10;
			if (num[last] > 1) {
				return false;
			}
		}
		return true;
	}

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		// 9876543210最大的数
//	        long big = 9876543210L;
//	        long a = (long) Math.sqrt(big);
//	        System.out.println(a);  //a=99380;
		int flag = 0;

		for (long i = 99380; i > 0; i--) {
			long t = i * i;
			if (sqrt_num1(t)) {
				System.out.println(t);
				flag = 1;
				break;
			}
			if (flag == 1) {
				break;
			}
		}
		scan.close();
	}
}
【神奇六位数】
java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
  //辅助boolean数组a[]
    static int[] six_num(int m){
      int[] arr = new int[10];
      for(int i=0;i<10;i++){
        arr[i] = 0;
      }
      while(m>0){
        int last =m%10;
        arr[last]++;
        m/=10;
      }
      return arr;
    } 
    static boolean eq(int[] a,int[] b){
      for(int i=0;i<10;i++){
        if(a[i]!=b[i]){
          return false;
        }
      }
      return true;
    }


    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //神奇六位数
        int start = 100000;
        int i=start;
        while(i<166666){
          int[] temp = six_num(i).clone();
          int j=2;
          int count = 0;
          while(j<7){
            int num = i*j;
//            String str = num+"";
//            //乘积的位数不是6位数
//            if(str.length()!=6){
//              j=8; //跳出循环
//            }
            
            int[] arr = six_num(num).clone();
            if(eq(temp,arr)){
              j++;
              count++;
            }else {
            	j=8;
            }
          }
          //不符合条件
          if(j==8){
            i++;
          }//正常跳出循环j==7
          if(j==7){
            System.out.println(i);
            i=166667;
            break;
          }
        }
        scan.close();
    }
}
【前缀判断】
java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
   	  static String start_with(String a,String b){
	      //是否 a 包含了 b 
	      if(a.startsWith(b)){
	        return a;
	      }else{
	        return "";
	      }
	    }

	    static void test(String a,String b){
	      String p =start_with(a,b);
	      if(p==""&&b!=""){
	        System.out.printf("[NO]\n");
	      }else{
	        System.out.printf("|%s|\n",p);  
	      }
	    } 

	    public static void main(String[] args) {
	        Scanner scan = new Scanner(System.in);
	        test("abcd","abc");
	        test("abcd","acb");
	        test("abcd","abcd");
	        test("abcd","abcd");
	        test("","abc");
	        test("","");
	        scan.close();
	       // System.out.println("".startsWith("abc"));
	    }
}

startsWith(String s); String对象的一个方法用来判断是否是前缀,返回值是++布尔类型++;

【最小公倍数和最大公因数】
java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    static void swap(int a,int b){
	      int temp;
	      temp = a;
	      a = b;
	      b = temp;
	    } 
	    static void myfunc(int a,int b){
	      int m,n,r;
	      //辗转相除法
	      //让第一个数字大
	      if(a<b){
	        swap(a,b);
	      }
	      //此时a>b m>n
	      //m n 保留最初的两个数
	      m = a;
	      n = b;
	      r = a%b;
	      while(r!=0) {
	    	  a = b;
	    	  b = r;
	    	  r = a%b;
	      }
	      //出来的时候说明r==0  即a能整除b
	      System.out.printf("%d\n",b);//最大公约数
	      System.out.printf("%d\n",b*(m/b)*(n/b)); //最小公倍数
	    }
	    public static void main(String[] args) {
	        Scanner scan = new Scanner(System.in);
	        myfunc(30,12);
	        myfunc(12*7,30);
	        scan.close();
	    }
}
相关推荐
咚咚轩4 小时前
蓝桥杯13届国B 完全日期
蓝桥杯·枚举·日期问题
逐光沧海16 小时前
数据结构基础--蓝桥杯备考
数据结构·c++·算法·蓝桥杯
吃个早饭18 小时前
2025年第十六届蓝桥杯大赛软件赛C/C++大学B组题解
c语言·c++·蓝桥杯
ErikTse_1 天前
【官方题解】StarryCoding 入门教育赛 2 | acm | 蓝桥杯 | 新手入门
职场和发展·蓝桥杯
嗨信奥1 天前
蓝桥杯青少 图形化编程(Scratch)每日一练——校门外的树
青少年编程·蓝桥杯
不見星空2 天前
2025年第十六届蓝桥杯软件赛省赛C/C++大学A组个人解题
c语言·c++·蓝桥杯
梁下轻语的秋缘2 天前
每日c/c++题 备战蓝桥杯(洛谷P1387 最大正方形)
c语言·c++·蓝桥杯
工藤新一¹2 天前
蓝桥杯算法题 -蛇形矩阵(方向向量)
c++·算法·矩阵·蓝桥杯·方向向量
咚咚轩2 天前
蓝桥杯13届 卡牌
蓝桥杯·贪心
梁下轻语的秋缘2 天前
每日c/c++题 备战蓝桥杯(洛谷P1115 最大子段和)
c语言·c++·蓝桥杯