CF698A Vacations

Description:

瓦西亚有n天的假期!所以他决定提高自己的IT技能并做运动。Vasya知道以下关于这n天的每一天的信息:该健身房是否开放以及当天是否在互联网上进行了比赛。第i天有四种选择:
在这一天,健身房关闭,比赛没有进行;
在这一天,健身房关闭,比赛进行;
在这一天,健身房开放,比赛没有进行;
在这一天,健身房开放,比赛进行。
在每一天,Vasya可以休息或写比赛(如果在这一天进行),或者做运动(如果健身房在这一天开放)。
找出Vasya休息的最少天数(这意味着他不会做运动并同时写比赛)。Vasya唯一的限制 - 他不想连续两天做同样的活动:这意味着,他不会连续两天做运动,连续两天写比赛。

Analysis

f[i][j] := 第i天做第j件事 (0: rest,1: contest,2:gym)
a[i] = 0,只能休息
a[i] = 1,休息 或 比赛
a[i] = 2,休息 或 运动
a[i] = 3,休息 或 运动 或 比赛

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 110
using namespace std;
// 0:rest 1:contest 2:sport
int a[N],f[N][3],n;
int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)
	{
		scanf("%d",&a[i]);
	}
	memset(f,0x3f,sizeof(f));
	f[1][0] = 1;
	if(a[1] == 1) f[1][1] = 0;
	if(a[1] == 2) f[1][2] = 0;
	if(a[1] == 3)
	{
		f[1][1] = f[1][2] = 0;
	}
	for(int i = 2;i <= n;++i)
	{
		f[i][0] = min(f[i-1][0],min(f[i-1][1],f[i-1][2])) + 1;
                //                            前一天休息加今天比赛, 前一天运动加今天比赛,  前一天比赛加今天休息
		if(a[i] == 1) f[i][1] = min(f[i-1][0],min(f[i-1][2],f[i-1][1] + 1));
                //                            前一天休息加今天运动, 前一天比赛加今天运动,  前一天运动加今天休息
		if(a[i] == 2) f[i][2] = min(f[i-1][0],min(f[i-1][1],f[i-1][2] + 1));
		if(a[i] == 3)
		{
			f[i][1] = min(f[i-1][0],min(f[i-1][2],f[i-1][1] + 1));
			f[i][2] = min(f[i-1][0],min(f[i-1][1],f[i-1][2] + 1));
		}
	}
	printf("%d
",min(f[n][0],min(f[n][1],f[n][2])));
	return 0;
}

岂能尽如人意,但求无愧我心
原文地址:https://www.cnblogs.com/Zforw/p/11107445.html