题目:
给出n天,你知道每天体育馆有没有开放,测试有没有开放,让你判断最少休息的天数,你不能连续2天运动或者测试。
每天需要判断三个决策:
1:休息 2:运动 3:测试
如果每天决策不同会影响答案,那么我们需要能够找出每天不同决策的最小答案。
用dp[i][0]记录如果今天是休息,那么今天为止的最少休息时间;
用dp[i][1]记录如果今天是运动,那么今天为止的最少休息时间;
用dp[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][2], dp[i - 1][0]); 今天运动,昨天只能休息或者测试,所以选择最小值
dp[i][2] = min(dp[i - 1][1], dp[i - 1][0]); 今天测试,昨天只能运动或者休息,选择它们之中的最小值
代码如下:
#include <iostream>
#include<algorithm>
using namespace std;
int main(void)
{
int a[1000],dp[1000][3]; //dp表示i天最少休息多少次
int n, i;
memset(dp, 100, sizeof(dp));
cin >> n;
for (i = 1; i <= n; i++) {
cin >> a[i];
}
/*b[i][0]表示第i天休息时,目前为止最少的休息时间
* b[i][1]表示第i天运动时,目前为止最少的休息时间
* b[i][2]表示第i天测试时,目前为止最少的休息时间
*/
dp[0][0]=0; //第一天之前可以看成什么都没做
for (i = 1; i<=n; i++) { //i从1开始,不用判断i-1,0-1是否越界
dp[i][0] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2])) + 1; //首先假使今天休息
if (a[i]==2||a[i]==3) {
dp[i][1] = min(dp[i - 1][2], dp[i - 1][0]); //昨天休息或者测试
}
if (a[i]==1 || a[i] == 3) {
dp[i][2] = min(dp[i - 1][1], dp[i - 1][0]); //昨天休息或做运动
}
/* 当是number3时,昨天可能做运动,可能测试,2者都要比较*/
}
cout <<min(dp[n][0],min(dp[n][1],dp[n][2]));
}