题意:有三种状态分别是休息,做事件A,做事件B,两种事件不能在同一天做,问怎么安排可以让休息的天数最少。每天可以做的事情可能是能做所有事情或者只能做一个或者只能休息 |
动态规划思路:
其实这道题的状态转移的影子很明显,当前如果可以做事情,那么当前的最优解一定是前面异于当前选择的最优解的最小值。
比如当前做事件A,那么最优解就是前一天做事件B的最优解和休息的最优解的最小值。即
dp[i][1]=min(dp[i-1][0],dp[i-1][2])。
对于其他状态也是一个道理。
最后答案就是在最后一天的三个状态里面挑最小就行了。
其实这个题和力扣上面这个题目是一个模子,看到我这篇博客的人有兴趣可以做一下。
#include <iostream>
#include <vector>
#include <cstdio>
#include <map>
#include <climits>
#include <string>
#include <cmath>
#include <cstring>
#include <algorithm>
#define maxn 105
using namespace std;
typedef long long ll;
static int inf = 0x3f3f3f3f;
int main()
{
int n;
cin>>n;
int a[105];
for(int i=1; i<=n; i++)
cin>>a[i];
vector<vector<int>> dp(105,vector<int>(3,inf));
dp[0][0]=0;
dp[0][1]=0;
dp[0][2]=0;//能做的事情无非三种
for(int i=1; i<=n; i++)
{
if(a[i]==0) //当前状态只能为0时,找出前面做0、做1,做2的最优解
{
dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1;
}
if(a[i]==1) //当前状态可以选择0或2时,找出对应之前的最优解
{
dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1; //当前
dp[i][2]=min(dp[i-1][0],dp[i-1][1]);
}
if(a[i]==2)
{
dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1;
dp[i][1]=min(dp[i-1][0],dp[i-1][2]);
}
if(a[i]==3)
{
dp[i][0]=min(dp[i-1][0],min(dp[i-1][1],dp[i-1][2]))+1;
dp[i][2]=min(dp[i-1][0],dp[i-1][1]);
dp[i][1]=min(dp[i-1][0],dp[i-1][2]);
}
}
int minone=inf;
for(int i=0;i<=3;i++)//最后一天在三种状态里面挑最小
minone=min(minone,dp[n][i]);
cout<<minone<<endl;
return 0;
}