腾讯2020年校园招聘笔试题,工作狂小Q所能休息的最小天数(动态规划dp)ACM模式,Java实现

腾讯2020年校园招聘笔试题,工作狂小Q所能休息的最小天数(动态规划)ACM模式,Java版

由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。

在这里插入图片描述在这里插入图片描述

package 动态规划;

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

/**
 * 题目:
 * 由于工作业绩优秀,公司给小Q放了n天的假,身为工作狂的小Q打算在假期中工作、锻炼和休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最小需要休息几天?
 *
 * 输入:
 * 第一行表示放假天数
 * 第二行n个数,0或1,表示公司第i天是否营业
 * 第三行表示健身房
 * 1为营业 0为不营业
 * ————————————————
 */
public class 小Q休假 {
    public static void main(String[] args) {
        Scanner sc =new Scanner(System.in);
        int len =sc.nextInt();//总天数
        int[] work =new int[len];// 每一天的公司状态 1营业 0关门
        int[] gym =new int[len];// 每一天的体育馆状态 1营业 0关门

        // 填充公司数组
        for (int i = 0; i < len; i++) {
            work[i] =sc.nextInt();
        }
        //填充体育馆数组
        for (int j = 0; j < len; j++) {
            gym[j] =sc.nextInt();
        }

        // dp[i][j] 表示 小Q在第i天工作0,健身1或休息2的话 算上之前总共休息的最小天数
        int[][] dp =new int[len][3];
        /**
         * 状态转移方程
         *  1、如果今天工作,则前一天必须为去体育馆或者休息
         *          dp[i][0] =Math.min(dp[i-1][1],dp[i-1][2])
         *  2、如果今天锻炼,则前一天必须为去工作或者休息
         *           dp[i][1] =Math.min(dp[i-1][0],dp[i-1][2])
         *  3、如果今天休息,则前几天可以为工作、锻炼、休息
         *          dp[i][2] =Math.min(dp[i-1][1],Math.min(dp[i-1][0],dp[i-1][2]))
         *
         *   注意: dp[i][j] 表示小Q在第i天进行j事所能休息的最小天数!(j=0,1,2  0-工作 1-锻炼 2-休息)
         *          比如 dp[2][1] = 2,代表小Q在第三天(从index=0开始)锻炼的话,总共休息的最小天数为2
         */

        // 因为数组默认值为0,先给他都填充Max_value
        for (int[] ints : dp) {
            Arrays.fill(ints, Integer.MAX_VALUE);
        }

        // 如果第一天公司营业,则必去上班,休息天数为0
        if (work[0] == 1){
            dp[0][0] =0;
        }
        // 如果第一天体育馆营业,则必去锻炼,休息天数为0
        if (gym[0] == 1){
            dp[0][1] =0;
        }
        // 如果第一天选择休息,则休息天数为1
        dp[0][2] =1;
        // 从第二天开始计
        for (int i = 1; i < len; i++) {
            // 如果公司开门的话 则:
            if (work[i] == 1){
                dp[i][0] =Math.min(dp[i-1][1],dp[i-1][2]);
            }
            // 如果体育馆开门的话 :
            if (gym[i] == 1){
                dp[i][1] =Math.min(dp[i-1][0],dp[i-1][2]);
            }
            // 选择休息的话
            dp[i][2] =Math.min(dp[i-1][1],Math.min(dp[i-1][0],dp[i-1][2]))+1;
        }
        // 最后一天选择工作、锻炼、休息 所能积攒的最小值就为结果
        int result =Math.min(dp[len-1][0],Math.min(dp[len-1][1],dp[len-1][2]));
        System.out.println(result);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值