复旦计算机2021机试

明天就要机试了,目前只做了2020年的题目,今天准备把2017-2021做完。

第一题

第一题看到很多思路是建树。但是完全二叉树可以用数组来表示,这时可以使用一个dp数组进行动态规划,记录到第n个数时最大的数是多少即可。

import java.util.Scanner;
public class A_2021 {
    static Scanner scanner=new Scanner(System.in);
    public static void main(String[] args) {
        String s = scanner.nextLine();
        String[] split = s.split(",");
        //num多出一个0位置 这是为了后面方便计算父元素节点
        int[] num=new int[split.length+1];
        int[] dp=new int[split.length+1];
        int i=1;
        int result=1;//根节点一定是关键节点
        for (String s1 : split) {
                if(!s1.equals("null")){
                    num[i++]=Integer.parseInt(s1);
                }else{
                    num[i++]=Integer.MIN_VALUE;
                }
        }
        dp[1]=num[1];
        for(i=2;i<split.length+1;i++){
            dp[i]=Math.max(dp[i/2],num[i]);
            if(num[i]==dp[i]) result++;
        }
        System.out.println(result);
    }
}

 第二题

第二题比第一题还要简单,是最基础的动态规划问题,直接上代码。

import java.util.Scanner;
public class B_2021 {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        int dp[]=new int[n];
        if(n==1){
            System.out.println(1);
            return;
        }
        dp[0]=1;
        dp[1]=2;
        for(int i=2;i<n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        System.out.println(dp[n-1]);
    }
}

第三题

这题出的很好,由于序列中本身都是非负数,所以如果出现负数一定是对其取负。期望值=正数+负数,总值=正数-负数,所以期望值+总值为两倍的正数值,这就化解成了背包问题,从这些数中取出指定数有多少种取法。需要用一个二维dp数组来解决。

对于每一个数,都有取和不取两种选项,dp[i][j]代表在前i个数中,取到j这个数有多少种方法,dp的最左边一列表示取0的方法数,都是1。最后返回dp[m-1][n]

import java.util.Scanner;
public class C_2021 {
    static Scanner scanner=new Scanner(System.in);
    public static void main(String[] args) {
        //读取数据 计算total
        String s = scanner.nextLine();
        int e=scanner.nextInt();
        String[] split = s.split(",");
        int[] num=new int[split.length];
        int total=0;
        for(int i=0;i<split.length;i++){
            num[i]=Integer.parseInt(split[i]);
            total+=num[i];
        }
        //初始化dp二维数组
        int E=(total+e)/2;
        int[][] dp=new int[split.length][E+1];
        for(int j=0;j<=E;j++){
            dp[0][j]=(j==0||j==num[0])?1:0;
        }
        
        //开始由递推数组进行计算
        for(int i=1;i<split.length;i++){
            for (int j=0;j<=E;j++){
                if(j==0) dp[i][j]=1;
                else{
                    if(E>=num[i]){
                        dp[i][j]=dp[i-1][j]+dp[i-1][j-num[i]];
                    }else{
                        dp[i][j]=dp[i-1][j];
                    }
                }
            }
        }
        
        //输出结果
        System.out.println(dp[split.length-1][E]);

    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值