首页 > 试题广场 >

假期

[编程题]假期
  • 热度指数:7689 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
由于业绩优秀,公司给小Q放了 n 天的假,身为工作狂的小Q打算在在假期中工作、锻炼或者休息。他有个奇怪的习惯:不会连续两天工作或锻炼。只有当公司营业时,小Q才能去工作,只有当健身房营业时,小Q才能去健身,小Q一天只能干一件事。给出假期中公司,健身房的营业情况,求小Q最少需要休息几天。

输入描述:
第一行一个整数  表示放假天数
第二行 n 个数 每个数为0或1,第 i 个数表示公司在第 i 天是否营业
第三行 n 个数 每个数为0或1,第 i 个数表示健身房在第 i 天是否营业
(1为营业 0为不营业)


输出描述:
一个整数,表示小Q休息的最少天数
示例1

输入

4
1 1 0 0
0 1 1 0

输出

2

说明

小Q可以在第一天工作,第二天或第三天健身,小Q最少休息2天
import java.util.Scanner;

/**
 * @Author: lei
 * @Date: 2020.3.18 10:21
 */
public class Holiday {
	public static void main(String[] args) {
		//第一步数据处理:三行,就是三个字符串,后两行进行一个分割处理,然后再调用函数转换成为整型数据
		Scanner in = new Scanner(System.in);
		String day_str = in.nextLine();
		String [] work_str = in.nextLine().split(" ");
		String [] gym_str = in.nextLine().split(" ");
		int day = Integer.parseInt(day_str);  //日期
		int [] works = new int[day+1];
		int [] gyms = new int[day+1];
		for(int i = 1;i < day+1;i++) {
			works[i] = Integer.parseInt(work_str[i - 1]);
			gyms[i] = Integer.parseInt(gym_str[i-1]);
		}
		int res = holiday(day, works, gyms);
		System.out.println(res);
	}
	
	//策略:使用dp[i][0] dp[i][1] dp[i][2]分别记录在第i天如果是休息、工作、健身情况下,前i天有事做(也就是没休息)的最大天数
	//如果第i天休息,那么前i天有事做的最大天数,实际就是dp[i-1][0] dp[i-1][1] dp[i-1][2]中的最大值
	//如果第i天工作,那么前i天有事做的最大天数,就是前一天休息、健身中的最大值 + 1(因为第i天工作了,没有休息)
	//如果第i天健身,那么前i天有事做的最大天数,就是前一天休息、工作中的最大值 + 1(因为第i天健身了,没有休息)
	//最后的结果,就用day减去最大的做事天数,就是最少的休息时间了
	public static int holiday(int day, int [] works, int [] gyms){
		int res;
		int [][] dp = new int[day+1][3];
		dp[0][0] = dp[0][1] = dp[0][2] = 0;
		for (int i = 1; i < day+1; i++) {
			if(works[i] == 1){
				//第i天可以选择工作
				dp[i][1] = Math.max(dp[i-1][0], dp[i-1][2]) + 1;
			}
			if(gyms[i] == 1){
				//第i天可以选择健身
				dp[i][2] = Math.max(dp[i-1][0], dp[i-1][1]) + 1;
			}
			dp[i][0] = Math.max(dp[i-1][0], Math.max(dp[i-1][1], dp[i-1][2]));
		}
		res = day - Math.max(dp[day][0], Math.max(dp[day][1], dp[day][2]));
		return res;
	}
}//class end

编辑于 2020-09-06 16:54:46 回复(6)
#include<bits/stdc++.h>
using namespace std;
using LL = int64_t;
const int maxn=1e5+5;
int dp[maxn][3],a[maxn],b[maxn];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) {
        dp[i][0]=max(dp[i-1][1]+a[i],dp[i-1][0]);
        dp[i][1]=max(dp[i-1][0]+b[i],dp[i-1][1]);
    }
    cout<<n-max(dp[n][0],dp[n][1]);
    return 0;
}


编辑于 2020-01-15 07:31:28 回复(1)

最直观的想法,算是一种贪心吧。

n = int(input())//3
work = list(map(int,input().split()))
gem = list(map(int,input().split()))
workok,gemok,cnt = 0,0,0//标记当天能去哪里,0表示可以去,1表示不能去,cnt为放假天数
for i in range(n):
    if work[i] == 0 and gem[i] == 0://都不开放,必须休息
        cnt += 1
        workok,gemok = 0,0
        continue
    if work[i] == 1 and gem[i] == 1://都开放,不能休息
        if workok == 0 and gemok == 0://两者都能去,需要根据明天情况判断今天是去哪里
            continue
        workok,gemok = gemok,workok//此时只允许去一个,状态对调
        continue
    if work[i] == 1://只有公司开
        if workok == 0:
            workok = 1
            gemok = 0
            continue
        cnt+=1
        workok,gemok = 0,0
    if gem[i] == 1://只有gem开
        if gemok == 0:
            gemok = 1
            workok = 0
            continue
        cnt+=1
        workok,gemok = 0,0
print(cnt)
发表于 2020-04-07 17:23:59 回复(0)
#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
int a[N],b[N];
int n;
int main(){
    cin>>n;
    for(int i =1;i<=n;i++){
        cin>>a[i];
    }
    for(int i =1;i<=n;i++){
        cin>>b[i];
    }
    int res = 0;
    int flag = 0;//0都可以选,1只能a,2只能选b;
    for(int i =1;i<=n;i++){
        if(a[i]==1&&b[i]==1&&flag==0){
            continue;
        }
        if(a[i]==1&&b[i]==1&&flag==1){
            flag =2;
            continue;
        }
         if(a[i]==1&&b[i]==1&&flag==2){
            flag =1;
            continue;
        }
         if(a[i]==0&&b[i]==1&&(flag==2||flag==0)){
            flag =1;
            continue;
        }
         if(a[i]==1&&b[i]==0&&(flag==1||flag==0)){
            flag =2;
            continue;
        }      
        res++;
        flag = 0;
    }
     cout<<res<<endl;
    return 0;
}

发表于 2021-11-24 19:20:55 回复(0)
三种情况下小Q必须休息。
1)公司健身房都不开
2)公司开,健身房不开,但昨天去过公司。
3)健身房开,公司不开,但昨天去过健身房
n = int(input())
a = [int(value) for value in input().split()]
b = [int(value) for value in input().split()]
result = 0
previous_a = 0
previous_b = 0
 
for i in range(n):
    if a[i] == 0 and b[i] == 0:
        result += 1
        previous_a = previous_b = 0
        continue
         
    if a[i] == 1 and b[i] == 0:
        if previous_a == 1:
            result += 1
            previous_a = previous_b = 0
            continue
        else:
            previous_a = 1
            previous_b = 0
            continue
             
    if a[i] == 0 and b[i] == 1:
        if previous_b == 1:
            result += 1
            previous_a = previous_b = 0
            continue
        else:
            previous_a = 0
            previous_b = 1
            continue
     
    if a[i] == 1 and b[i] == 1:
        if previous_a == 1:
            previous_a = 0
            previous_b = 1
            continue
        if previous_b == 1:
            previous_b = 0
            previous_a = 1
            continue
        if previous_b == 0 and previous_a == 0:
            continue
print(result)


发表于 2021-04-02 13:07:20 回复(0)
使用动态规划进行求解,dp[i][0]、dp[i][1]、dp[i][2]分别表示第i天休息、健身、工作时,累积到今天的最少休息天数,得到以下三种情况的状态转移方程:
1.假如第i天健身房开门且选择健身,健身可以从休息和工作两个状态转移过来,因为今天选择了截健身,所以止到今天的累积休息天数并不会增加
dp[i][1] = min(dp[i - 1][0], dp[i - 1][2])
2.假如第i天单位开门且选择工作,工作可以从休息和健身两个状态转移过来,因为今天选择了工作,所以截止到今天的累积休息天数并不会增加
dp[i][2] = min(d[i - 1][0], dp[i - 1][1])
3.假如第i天休息,休息可以从休息、健身和工作三个状态转移过来,因此截止到今天的累积休息天数会增加一天
dp[i][0] = min(dp[i - 1][0], dp[i - 1][1], dp[i - 1][2]) + 1
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());
        String[] strIsWorking = br.readLine().trim().split(" ");
        String[] strIsGym = br.readLine().trim().split(" ");
        int[] isWorking = new int[n];
        int[] isGym = new int[n];
        for(int i = 0; i < n; i++){
            isWorking[i] = Integer.parseInt(strIsWorking[i]);
            isGym[i] = Integer.parseInt(strIsGym[i]);
        }
        // dp[i][0],dp[i][1],dp[i][2]分别表示第i天 休息/锻炼/工作 累计的最小休息天数
        int[][] dp = new int[n + 1][3];
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < 3; j++) dp[i][j] = Integer.MAX_VALUE;
        for(int i = 1; i <= n; i++){
            // 今天健身房开门,锻炼从另外两种状态转移过来
            if(isGym[i - 1] == 1)
                dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]);
            // 今天单位开门,工作从另外两种状态转移过来
            if(isWorking[i - 1] == 1)
                dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]);
            // 休息可以从自身或另外两种状态转移而来
            dp[i][0] = Math.min(dp[i - 1][0], Math.min(dp[i - 1][1], dp[i - 1][2])) + 1;
        }
        System.out.println(Math.min(dp[n][0], Math.min(dp[n][1], dp[n][2])));
    }
}


编辑于 2021-02-04 18:41:07 回复(0)
参考评论中动归思路,仿照写了javascript代码,值得注意的是js需创建dp二维数组。
    let nDayoff = readline();
    let workStr = readline();
    let gymStr = readline();

    let work = workStr.split(' ').map(Number);
    let gym = gymStr.split(' ').map(Number);
    let len = work.length;
    
    let dp = new Array(nDayoff + 1);
    for (let i = 0; i < nDayoff + 1; i++) {
        dp[i] = new Array(3).fill(Infinity);
    }
    //console.log("dp:", dp);

    dp[0][0] = dp[0][1] = dp[0][2] = 0;
    for (let i = 1; i <= len; i++) {
        if (gym[i - 1] === 1) {
            // 可以锻炼
            dp[i][1] = Math.min(dp[i - 1][0], dp[i - 1][2]);
        }
        if (work[i - 1] === 1) {
            //可以工作
            dp[i][2] = Math.min(dp[i - 1][0], dp[i - 1][1]);
        }
        //可以休息
        dp[i][0] = Math.min(dp[i - 1][0], Math.min(dp[i - 1][1], dp[i - 1][2])) + 1;
    }
    let res = Math.min(dp[len][0], Math.min(dp[len][1], dp[len][2]));
    console.log(res);


发表于 2020-08-25 15:52:52 回复(0)
参考了滑雪冰橙的回答,java版:
dp[i][0] : 代表第i天是休息,0...i天最少的休息日数量
dp[i][1] : 代表第i天是健身,0...i天最少的休息日数量
dp[i][2] : 代表第i天是工作,0...i天最少的休息日数量
import java.util.Scanner;
public  class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            int[] wo = new int[n];
            for (int i = 0; i < n; i++) {
                wo[i] = in.nextInt();
            }
            int[] ex = new int[n];
            for (int i = 0; i < n; i++) {
                ex[i] = in.nextInt();
            }
            System.out.println(minDay(wo, ex));
        }
    }

  

    public static int minDay(int[] wo, int[] ex) {
        int n = wo.length;
        int[][] dp = new int[n][3];
        // 0 休息,1 健身,2 工作
        dp[0][0] = wo[0] == 0 && ex[0] == 0 ? 1 : 0;
        dp[0][1] = wo[0] == 0 ? Integer.MAX_VALUE : 0;
        dp[0][2] = ex[0] == 0 ? Integer.MAX_VALUE : 0;

        for (int i = 1; i < n; i++) {

            dp[i][2] = wo[i] == 1 ? 
                Math.min(dp[i - 1][0], dp[i - 1][1]) : Integer.MAX_VALUE;

            dp[i][1] = ex[i] == 1 ? 
                Math.min(dp[i - 1][0], dp[i - 1][2]) : Integer.MAX_VALUE;

            dp[i][0] = Math.min(dp[i - 1][0], Math.min(dp[i - 1][1], dp[i - 1][2])) + 1;
        }

        return Math.min(dp[n - 1][0], Math.min(dp[n - 1][1], dp[n - 1][2]));
    }
}


发表于 2020-08-21 14:18:44 回复(3)
day=int(input())
_C=input()
c=[int(i) for i in _C.split()]
_G=input()
g=[int(i) for i in _G.split()]
 
a=[c.copy(),g.copy()]
 
for i in range(day-1):
    if c[i]==0:
        a[0][i+1]+=a[0][i] if a[0][i] > a[1][i] else a[1][i]
    else:
        a[0][i+1]+=a[1][i]
    if g[i]==0:
        a[1][i+1]+=a[0][i] if a[0][i] > a[1][i] else a[1][i]
    else:
        a[1][i+1]+=a[0][i]
 
print(day-(a[0][day-1] if a[0][day-1]>a[1][day-1] else a[1][day-1]))
a[:][i]表示到第i天为止已经工作或运动的天数。

编辑于 2020-07-02 17:37:04 回复(0)
画个状态机,一目了然.. dp[i][0] , dp[i][1], dp[i][2] 分别记录第i天 休息/锻炼/工作 累计的最小休息天数.. 状态转移关系如下图..     

# include <iostream>
# include <cstdlib>
# include <cstring>
# include <stack>
# define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
 
int main(void){
    int n ;
    while(cin>>n){
        int gym[n],i, work[n];
        for ( i=0; i<n; ++i )
            cin>>work[i];
        for( i=0; i<n; ++i )
            cin>>gym[i];
        int dp[n+1][3]; // 0是休息,1是锻炼,2是工作
        memset(dp, 0x3f, sizeof(dp));
        dp[0][0] = dp[0][1] = dp[0][2] = 0;
        for ( int i=1; i<=n; ++i ){
            if ( gym[i-1] == 1 ){
                // 可以锻炼
                dp[i][1] = min( dp[i-1][0], dp[i-1][2] );
            }
            if ( work[i-1] == 1 ){
                // 可以工作
                dp[i][2] = min( dp[i-1][0], dp[i-1][1] );
            }
            dp[i][0] = min(dp[i-1][0], min(dp[i-1][1], dp[i-1][2]))+1;
        }
        int res = min(dp[n][0], min(dp[n][1], dp[n][2]));
        cout<<res<<endl;
    }
    return 0;
}


发表于 2020-02-12 00:15:48 回复(15)

1 前言

太久没写题了,在做套题时想不起如何写方程组。看了题解,恍然大悟(就是觉得自己好菜,怎么这么简单的解题思路也忘记了)。学习了@清雪冰橙 大佬的代码,重新整理了一下解题思路,如下所述。

2 解题算法

动态规划

3 解题思路

3.1 状态转移分析

1、每一天小Q都可能处于3个状态,那就是工作、休息、锻炼
2、若第i天小Q处于工作状态,那么第i-1天只能是休息、锻炼
3、若第i天小Q处于锻炼状态,那么第i-1天只能是休息、工作
4、若第i天小Q处于休息状态,那么第i-1天可能是工作、休息、锻炼。

3.2 方程组

基于上述逻辑思路,我们可以用dp[i][0]、dp[i][1]、dp[i][2]分别表示第i天小Q处于休息、工作、锻炼时最少的休息天数。
那么,可得如下状态转移方程式:
//1. 选择休息,故天数多1
dp[i][0] = min(dp[i-1][0], min(dp[i-1][1], dp[i-1][2])) + 1; 
//2. 不休息,选择工作
dp[i][1] = min(dp[i-1][0], dp[i-1][2]); 
//3. 不休息,选择锻炼
dp[i][2] = min(dp[i-1][0], dp[i-1][1]); 
//边界:第0天休息天数为0
dp[0][i] = 0 (i = 1, 2, 3) 


最后只需拿出第n天各种状态下的最少天数,即为答案。

4 实现代码

# include<iostream>
# include<memory>
using namespace std;
int dp[100010][3];
int work[100010];
int train[100010];
int main(){
    int n;
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> work[i];
    }
    for (int i = 0; i < n; i++){
        cin >> train[i];
    }
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = dp[0][1] = dp[0][2] = 0;
    for (int i = 1; i <= n; i++)
    {
        //看看今天是否能工作
        if (work[i-1] == 1){
            dp[i][1] = min(dp[i-1][0], dp[i-1][2]);
        } 
        //看看今天是否能锻炼
        if (train[i-1] == 1){
            dp[i][2] = min(dp[i-1][0], dp[i-1][1]);
        } 
        dp[i][0] = min(dp[i-1][0], min(dp[i-1][1], dp[i-1][2])) + 1; //休息多1天

    }
    int ans = min(dp[n][0], min(dp[n][1], dp[n][2]));
    cout << ans << endl;
    return 0;
}


编辑于 2020-08-21 13:19:33 回复(2)
动态规划,dp中记录3中状态下有事可做的最多天数,休息(dp[0][i])、健身(dp[1][i])、工作(dp[2][i])。
dp[0][i] = max(dp[0][i - 1], max(dp[1][i - 1], dp[2][i - 1]));休息无事可做,值为前一天3中状态下的最大值。
dp[1][i] = max(dp[2][i - 1], dp[0][i - 1]) + 1;选择健身,值为前一天休息和工作的最大值+1。
dp[2][i] = max(dp[1][i - 1], dp[0][i - 1]) + 1;选择工作,值为前一天休息和健身的最大值+1。
最后输出n减去最后一天三种状态下的最大值。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<int> work(n), slp(n);
	for (int i = 0; i < n; ++i)
		cin >> work[i];
	for (int i = 0; i < n; ++i)
		cin >> slp[i];
	vector<vector<int>> dp(3, vector<int>(n + 1));
	dp[0][0] = dp[1][0] = dp[2][0] = 0;
	for (int i = 1; i <= n; ++i) {
		dp[0][i] = max(dp[0][i - 1], max(dp[1][i - 1], dp[2][i - 1]));
		if (slp[i - 1]) {
			dp[1][i] = max(dp[2][i - 1], dp[0][i - 1]) + 1;
		}
		if (work[i - 1]) {
			dp[2][i] = max(dp[1][i - 1], dp[0][i - 1]) + 1;
		}
	}
	cout << n - max(dp[0][n], max(dp[1][n], dp[2][n])) << endl;

	return 0;
}


编辑于 2020-02-28 11:40:23 回复(3)
三状态dp, 极致简洁
时间O(n) 空间O(1)
#include <iostream>
#include <vector>
using namespace std;

void printLeastRelax(vector<int> &a, vector<int> &b){
    int n = a.size();

    int dp0 = 1;
    int dp1 = a[0] ? 0 : n;
    int dp2 = b[0] ? 0 : n;
    for(int i = 1; i < n; ++i){
        int prev_dp0 = dp0;
        int prev_dp1 = dp1;
        int prev_dp2 = dp2;

        dp0 = min(prev_dp0, min(prev_dp1, prev_dp2)) + 1; 
        dp1 = a[i] ? min(prev_dp0, prev_dp2) : n;
        dp2 = b[i] ? min(prev_dp0, prev_dp1) : n;
    }
    cout << min(dp0, min(dp1, dp2)) << endl;
}

int main() {
    int n;
    vector<int> a;
    vector<int> b;
    
    cin >> n;
    a.resize(n);
    b.resize(n);
    for(int i = 0; i < n; ++i){
        cin >> a[i];
    }
    for(int i = 0; i < n; ++i){
        cin >> b[i];
    }

    printLeastRelax(a,b);
}
// 64 位输出请用 printf("%lld")


编辑于 2023-03-26 00:35:17 回复(0)
欢迎大家批评指正:
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int n = in.nextInt();
            int[] nums1 = new int[n]; // 工作
            int[] nums2 = new int[n]; // 健身
            for (int i = 0; i < n; i++) {
                nums1[i] = in.nextInt();
            }
            for (int i = 0; i < n; i++) {
                nums2[i] = in.nextInt();
            }
            int work = 0;
            for (int i = 0; i < n; i++) {
                if (nums1[i] == 1 && nums2[i] == 1) { // 都为营业,选一个(不必关心具体选哪个)
                    work++;
                } else if (nums1[i] == 1) { // 只营业一个,则就选营业的那个(贪心思想)
                    work++;
                    if (i + 1 < n) nums1[i + 1] = 0; // 选了营业的,就将对应的明天的营业状态置为0(因为不能两天选一家)
                } else if (nums2[i] == 1) {
                    work++;
                    if (i + 1 < n) nums2[i + 1] = 0;
                }
            }
            System.out.println(n - work);
        }
    }
}


发表于 2023-03-04 14:10:00 回复(0)
回溯算法实现
package tencent;

import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;

public class Main {
    private static int min = Integer.MAX_VALUE;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] c = new int[n];
        int[] y = new int[n];
        for (int i = 0; i < n; i++) {
            c[i] = scanner.nextInt();
        }
        for (int i = 0; i < n; i++) {
            y[i] = scanner.nextInt();
        }
        backtrack(-1, c, y, 0, n, 0);
        System.out.println(min);
    }

    /**
     * 回溯法解决问题,只有两种选择
     *
     * @param last  上一个选择,0 代表公司,1 代表健身房
     * @param c     公司列表
     * @param j     健身房列表
     * @param i     当前要进行选择的位置
     * @param n     总共要选择的次数
     * @param cRest 当前已经休息的次数
     */
    public static void backtrack(int last, int[] c, int[] j, int i, int n, int cRest) {
        // 判断是否已经超过了
        if (n == i) {
            if (cRest < min) {
                min = cRest;
            }
            return;
        }

        if (last == -1) {
            // 代表上一次没有选择,其他条件允许情况下可以选择公司或健身房
            if (c[i] == 1) {
                // 选择公司
                backtrack(0, c, j, i + 1, n, cRest);
            }
            if (j[i] == 1) {
                // 选择健身房
                backtrack(1, c, j, i + 1, n, cRest);
            }

            // 选择在家休息
            backtrack(-1, c, j, i + 1, n, cRest + 1);
        } else {
            // 上一次存在选择的情况
            if (last == 0) {
                // 上一次选择了公司
                if (j[i] == 1) {
                    // 选择健身房
                    backtrack(1, c, j, i + 1, n, cRest);
                }
                // 在家休息
                backtrack(-1, c, j, i + 1, n, cRest + 1);
            } else {
                // 上一次选择了健身房
                if (c[i] == 1) {
                    // 选择公司
                    backtrack(0, c, j, i + 1, n, cRest);
                }
                // 在家休息
                backtrack(-1, c, j, i + 1, n, cRest + 1);
            }
        }
    }
}


发表于 2022-04-24 17:55:25 回复(0)
看了几分代码,都是有判断当天健身房和公司开不开的,其实不需要判断,将dp数组初始化为最大天数,相应的状态转移减掉当天的开放状态即可。
也是三个状态:0(什么都不干),1(健身),2(搬砖)
状态转移为
 dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]));
 dp[i][1]=min(dp[i-1][0]-jianshen[i],dp[i-1][2]-jianshen[i]);
 dp[i][2]=min(dp[i-1][0]-gongsi[i],dp[i-1][1]-gongsi[i]);



#include <iostream>
#include <vector>

using namespace std;

int main(){
    int n;
    cin>>n;
    vector<int> gongsi,jianshen;
    for(int i=0;i<n;i++){
        int tmp;
        cin>>tmp;
        gongsi.push_back(tmp);
    }
    for(int i=0;i<n;i++){
        int tmp;
        cin>>tmp;
        jianshen.push_back(tmp);
    }   
    vector<vector<int>> dp(n,vector<int>(3,n));
    dp[0][1]-=jianshen[0];
    dp[0][2]-=gongsi[0];
    for(int i=1;i<n;i++){
        dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]));
        dp[i][1]=min(dp[i-1][0]-jianshen[i],dp[i-1][2]-jianshen[i]);
        dp[i][2]=min(dp[i-1][0]-gongsi[i],dp[i-1][1]-gongsi[i]);
    }
    cout<<min(dp[n-1][0],min(dp[n-1][1],dp[n-1][2]));
}





发表于 2022-03-18 10:48:33 回复(0)
 import java.util.*;

   public class Main{
        public static void main(String args[]){
              Scanner sc=new Scanner(System.in);
             int n=sc.nextInt();
             int works[]=new int[n];
             int free[]=new int[n];
             for(int i=0;i<n;i++){
                     works[i]=sc.nextInt();
             }
             for(int i=0;i<n;i++){
                     free[i]=sc.nextInt();
             }
               int dp[][]=new int[n+1][3];
                   for(int i=1;i<n+1;i++){
                       dp[i][0]=Math.min(dp[i-1][0],Math.min(dp[i-1][1],dp[i-1][2]))+1;
                       dp[i][1]=Math.min(dp[i-1][0],dp[i-1][2]);
                       dp[i][2]=Math.min(dp[i-1][0],dp[i-1][1]);
                       if(works[i-1]==0){
                           dp[i][1]=Integer.MAX_VALUE;
                       }   
                       if(free[i-1]==0){
                           dp[i][2]=Integer.MAX_VALUE;
                       }
                   }
            int ans=Math.min(dp[n][0],Math.min(dp[n][1],dp[n][2]));
             System.out.println(ans);
             
        }
   }
发表于 2022-03-17 23:48:20 回复(0)
import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr1 = new int[n];
        int[] arr2 = new int[n];

        for (int i = 0; i < n; i++) {
            arr1[i] = scanner.nextInt();
        }

        for (int i = 0; i < n; i++) {
            arr2[i] = scanner.nextInt();
        }
        // 休息,工作,锻炼
        int[][] dp = new int[n][3];
        for (int i = 0; i < n; i++) {
            if (i == 0) {
                dp[i][0] = 1;
                dp[i][1] = arr1[i] == 1 ? 0 : Integer.MAX_VALUE;
                dp[i][2] = arr2[i] == 1 ? 0 : Integer.MAX_VALUE;
            } else {
                dp[i][0] = Math.min(Math.min(dp[i - 1][0], dp[i - 1][1]), dp[i - 1][2]) + 1;
                dp[i][1] = arr1[i] == 1 ? Math.min(dp[i - 1][0], dp[i - 1][2]) : Integer.MAX_VALUE;
                dp[i][2] = arr2[i] == 1 ? Math.min(dp[i - 1][0], dp[i - 1][1]) : Integer.MAX_VALUE;
            }
        }
//        for (int i = 0; i < n; i++) {
//            System.out.println(Arrays.toString(dp[i]));
//        }
        System.out.println(Math.min(Math.min(dp[n - 1][0], dp[n - 1][1]), dp[n - 1][2]));
    }
}
发表于 2022-03-07 12:45:13 回复(0)
import java.util.Scanner;
//dp思路反求最大的,第一眼看以为贪心2分后来发现贪心无效,类似于买股票问题很好想
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] comp = new int[n],paly = new int[n];
        for (int i = 0; i < n; i++) {
            comp[i] = scanner.nextInt();
        }
        for (int i = 0; i < n; i++) {
            paly[i] = scanner.nextInt();
        }
        System.out.println(retireday(comp,paly));
    }

    private static int retireday(int[] comp, int[] paly) {
        int work = 0,play = 0,retire = 0;
        for (int i = 0; i < comp.length; i++) {
            int w = work,p = play,r = retire;
            if(comp[i]==1)
                work = Math.max(p,r)+1;//由于不能是连续工作那么就是pr的最大值+1
            if(paly[i]==1)
                play = Math.max(w,r)+1;//同理上面
            retire = Math.max(w,p);//选最大的一个
        }
        int max = Math.max(Math.max(work,play),retire);
        return comp.length-max;
    }
    
}

发表于 2022-02-10 19:43:41 回复(0)
#include <bits/stdc++.h>
 
using namespace std;
 
int main() {
    int n;
    cin >> n;
    vector<int> work(n), exer(n);
    for (int i = 0; i < n; ++i) {
        cin >> work[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> exer[i];
    }
    vector<vector<int>> dp(3, vector<int>(n + 1, 0));
    // dp[1][i] -- work on the ith day
    // dp[2][i] -- exercise on the ith day
    // dp[0][i] -- rest on the ith day
    for (int i = 0; i < n; ++i) {
        if (work[i]) {
            dp[1][i + 1] = max(dp[0][i], dp[2][i]) + 1;
        } else {
            dp[1][i + 1] = max(dp[0][i], max(dp[1][i], dp[2][i]));
        }
        if (exer[i]) {
            dp[2][i + 1] = max(dp[0][i], dp[1][i]) + 1;
        } else {
            dp[2][i + 1] = max(dp[0][i], max(dp[1][i], dp[2][i]));
        }
        dp[0][i + 1] = max(dp[0][i], max(dp[1][i], dp[2][i]));
    }
    cout << n - max(dp[0][n], max(dp[1][n], dp[2][n])) << endl;
     
    return 0;
}
发表于 2021-09-27 20:17:54 回复(0)