感觉初学dp和递归有点像,从最终状态入手,然后推出现这种状态的前一个状态。
题目
题目描述
逛完美丽的校园,HJ发觉自己还有毕业设计没有做完,苦逼的HJ准备了n天的时间来完成他的毕业设计,按他的设想, 计划中的时间将在课设前端, 课设后端, 娱乐, 这三件事中度过,;
他进行了项目排期, 他不会两天连续做前端或做后端, 只有当排期为第i天做前端时, 他才在第i天做前端, 当排期为第i天做后端时, 他才在第i天做后端, 他一天只能做一件事, 要么前端, 要么后端, 要么娱乐,;
现在随机生成n天计划的排期, 求HJ最少能娱乐几天。
输入
第一行一个整数 n, n(1≤n≤100000) 表示天数n;
第二行 n 个数 每个数为0或1,第 i 个数表示hj在第 i 天是否能做前端(1为能做前端, 0为不能做前端);
第三行 n 个数 每个数为0或1,第 i 个数表示hj在第i天是否能做后端(1为能做后端, 0为不能做后端);
输出
一个整数, 表示hj最小娱乐天数。
样例输入
5
0 1 1 0 0
0 0 1 1 0
样例输出
3
提示
HJ可在第一天休息, 第二天做前端, 第三天或第四天做后端(第三天或第四天一天休息), 第五天休息, 最少休息三天。
思路
想要最少的休息时间就是要找到最多的学习时间。
然后前一天学前端第二天就一定不能学前端,所以在前端后一定会指向后端,因为指向后端学习的天数一定大于等于前端。
所以指向前端,的可能性就是前一个前端(不能加这个前端)和前一个后端(加这个前端),然后比较大小。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[2][100050], n;
int dp[2][100050];
int main()
{
cin>>n;
for(int i=0; i<n; i++)
cin>>a[0][i];
for(int i=0; i<n; i++)
cin>>a[1][i];
for(int i=0; i<n; i++)
{
dp[1][i+1]=max(dp[0][i]+a[1][i], dp[1][i]);
dp[0][i+1]=max(dp[1][i]+a[0][i], dp[0][i]);
}
cout<<n-max(dp[1][n-1], dp[0][n-1]);
return 0;
}