伏犬 要安排他接下来 nn 天的生活,他每天可以休息,打比赛或者去锻炼。他知道接下来 nn 天的信息,每天会有四种情况。
0、体育馆不开门,网络上没有比赛。
1、体育馆不开门,网络上有比赛。
2、体育馆开门,网络上没有比赛。
3、体育馆开门,网络上有比赛。
伏犬 不想连续两天打比赛,或者连续两天锻炼(但是可以连续两天休息)。
由于 伏犬 很懒,请你帮他安排一个休息天数最少的计划。
输入格式
第一行仅有一个数字 T(1\le T\le 10)T(1≤T≤10) 代表数据组数。下面依次是每一组数据
每组数据两行,第一行一个整数 n(1\le n\le 100)n(1≤n≤100),代表总天数。
第二行 nn 个整数 a_i(0 \le a_i \le 3)ai(0≤ai≤3) 代表每一天的情况。
输出格式
每组数据一行一个数字,表示最小休息天数。
样例
样例输入
3
4
1 3 2 0
7
1 3 3 2 1 2 3
2
2 2
样例输出
2
0
1
思路:一看题dp嘛推出每个到i位置的所有状态的最小休息数初始条件是inf然后啥都没有一开始没有长度都初始化为0然后枚举每种状态的答案和如何得来的方式输出所有方案的最小解即可,俺也会自己推dp了
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 109;
int a[maxn];
int dp[maxn][5];//第一个是到第i位置的情况第二个是第i位置是那种状况的最小解
int main() {
int t;
scanf("%d", &t);
while(t--) {
int n;
scanf("%d", &n);
for(int i = 1;i <= n;++i) {
scanf("%d", &a[i]);
}
memset(dp, inf, sizeof(dp));
for(int i = 0;i <= 2;++i) {
dp[0][i] = 0;
}
for(int i = 1;i <= n;++i) {
if(a[i] == 0) {
for(int j = 0;j <= 2;++j) {
dp[i][0] = min(dp[i-1][j]+1, dp[i][0]);
}
}//为0时只能从下面所有推到0
else if(a[i] == 1) {
for(int j = 0;j <= 2;++j) {
if(j == 1) {
dp[i][0] = min(dp[i][0], dp[i-1][1] + 1);
}
else {
dp[i][1] = min(dp[i-1][j], dp[i][1]);
}
}
}//为1时可以推到0或1,上一位为1时推到0为其他推到1
else if(a[i] == 2) {
for(int j = 0;j <= 2;++j) {
if(j == 2) {
dp[i][0] = min(dp[i][0], dp[i-1][2] + 1);
}
else {
dp[i][2] = min(dp[i-1][j], dp[i][2]);
}
}
}//为2时可以推到2和0,上一位为2时推到0为其他推到2
else {
for(int j = 0;j <= 2;++j) {
if(j == 1) {
dp[i][2] = min(dp[i][2], dp[i-1][j]);
}
else if(j == 2){
dp[i][1] = min(dp[i][1], dp[i-1][j]);
}
else {
dp[i][2] = min(dp[i][2], dp[i-1][j]);
dp[i][1] = min(dp[i][1], dp[i-1][j]);
}
}
}//上一位为1推到2上一位为2推到1其他推到1和2
}
printf("%d\n", min(dp[n][0], min(dp[n][1], dp[n][2])));//输出最优解
}
return 0;
}