腾讯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);
}
}