Codeforces Round #363 (Div. 2) C dp或贪心 两种方法

Description

Vasya has n days of vacations! So he decided to improve his IT skills and do sport. Vasya knows the following information about each of this n days: whether that gym opened and whether a contest was carried out in the Internet on that day. For the i-th day there are four options:

  1. on this day the gym is closed and the contest is not carried out;
  2. on this day the gym is closed and the contest is carried out;
  3. on this day the gym is open and the contest is not carried out;
  4. on this day the gym is open and the contest is carried out.

On each of days Vasya can either have a rest or write the contest (if it is carried out on this day), or do sport (if the gym is open on this day).

Find the minimum number of days on which Vasya will have a rest (it means, he will not do sport and write the contest at the same time). The only limitation that Vasya has — he does not want to do the same activity on two consecutive days: it means, he will not do sport on two consecutive days, and write the contest on two consecutive days.

Input

The first line contains a positive integer n (1 ≤ n ≤ 100) — the number of days of Vasya‘s vacations.

The second line contains the sequence of integers a1, a2, ..., an (0 ≤ ai ≤ 3) separated by space, where:

  • ai equals 0, if on the i-th day of vacations the gym is closed and the contest is not carried out;
  • ai equals 1, if on the i-th day of vacations the gym is closed, but the contest is carried out;
  • ai equals 2, if on the i-th day of vacations the gym is open and the contest is not carried out;
  • ai equals 3, if on the i-th day of vacations the gym is open and the contest is carried out.

Output

Print the minimum possible number of days on which Vasya will have a rest. Remember that Vasya refuses:

  • to do sport on any two consecutive days,
  • to write the contest on any two consecutive days.

Sample Input

Input

41 3 2 0

Output

2

Input

71 3 3 2 1 2 3

Output

0

Input

22 2

Output

1

题意:给你n天的情况     0 代表休息     1 代表只能参加contest或休息     2 代表只能参加gym或休息     3 代表能参加contest或gym或休息要求 不能连续参加contest 不能连续参加gym问 如何安排使得休息日最少 输出休息日的数量

题解: dp处理  dp[i][j] 代表 第i天进行j活动的情况下的前i天的最多非休息日的数量三个状态的转移方程     
dp[i][1]=max(dp[i-1][2],dp[i-1][0])+1;dp[i][2]=max(dp[i-1][1],dp[i-1][0])+1;dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2]);

结果为n-max(max(dp[n][0],dp[n][1]),dp[n][2])
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int n;
 6 int a[105];
 7 int dp[105][4];
 8 int main()
 9 {
10     scanf("%d",&n);
11     memset(dp,0,sizeof(dp));
12     for(int i=1;i<=n;i++)
13         scanf("%d",&a[i]);
14     if(a[1]==0)
15     dp[1][0]=0;
16     if(a[1]==1)
17     dp[1][1]=1;
18     if(a[1]==2)
19     dp[1][2]=1;
20     if(a[1]==3)
21     {
22         dp[1][1]=1;
23         dp[1][2]=1;
24         dp[1][0]=0;
25     }
26     for(int i=2;i<=n;i++)
27     {
28       if(a[i]==1)
29       {
30           dp[i][1]=max(dp[i-1][2],dp[i-1][0])+1;
31           dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2]);
32       }
33       if(a[i]==2)
34       {
35           dp[i][2]=max(dp[i-1][1],dp[i-1][0])+1;
36           dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2]);
37       }
38       if(a[i]==0)
39       {
40           dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2]);
41       }
42       if(a[i]==3)
43       {
44             dp[i][1]=max(dp[i-1][2],dp[i-1][0])+1;
45             dp[i][2]=max(dp[i-1][1],dp[i-1][0])+1;
46             dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2]);
47       }
48     }
49     int ans=0;
50     for(int i=0;i<=2;i++)
51         ans=max(ans,dp[n][i]);
52     cout<<n-ans<<endl;
53     return 0;
54 }

贪心处理  我gou代码

重点在3状态的处理上  若当前状态为3 则判断前一天状态

若前一天为1状态 则 将当前状态改为2  非休息日++

若前一天为2状态 则 将当前状态改为1  非休息日++

若前一天为0状态 则 将当前状态改为0  非休息日++ 当前状态改为0意味着 无论后一个状态为什么

当前这一天都有相应的状态可以更改 使得当前这一天为非休息日  即当前这一天 对后一天没有影响。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <map>
 9 #include <set>
10 #include <stack>
11 #include <sstream>
12 #include <vector>
13 #define PI acos(-1.0)
14 const int  inf =  (1<<30) - 10;
15 using namespace std;
16 inline int get_int()
17 {
18     int r=0;
19     char c;
20     while((c=getchar())!=‘ ‘&&c!=‘\n‘)
21         r=r*10+c-‘0‘;
22     return r;
23 }
24 inline void out(int x)
25 {
26     if(x>10)
27     {
28         out(x/10);
29     }
30     putchar(x % 10 + ‘0‘);
31     putchar(‘\n‘);
32 }
33 /****************************************/
34 int a[200];
35 int main()
36 {
37     int n,m;
38     cin>>n;
39     for(int i=0;i<n;i++){
40         scanf("%d",&a[i]);
41     }
42     m=0;
43     if(a[0]>0){
44         m++;
45     }
46     if(a[0]==3)
47         a[0]=0;
48     for(int i=1;i<n;i++){
49         if(a[i]==1){
50             if(a[i-1]!=1)
51                m++;
52             else a[i]=0;
53         }
54         if(a[i]==2){
55             if(a[i-1]!=2)
56                m++;
57             else a[i]=0;
58         }
59         if(a[i]==3){
60             if(a[i-1]==1){
61                 a[i]=2;
62                 m++;
63             }
64             if(a[i-1]==2){
65                 a[i]=1;
66                 m++;
67             }
68             if(a[i-1]==0){
69                 a[i]=0;
70                 m++;
71             }
72         }
73     }
74     printf("%d\n",n-m);
75     return 0;
76 }
时间: 2024-10-21 00:34:22

Codeforces Round #363 (Div. 2) C dp或贪心 两种方法的相关文章

Codeforces Round #261 (Div. 2) E (DP)

E. Pashmak and Graph Pashmak's homework is a problem about graphs. Although he always tries to do his homework completely, he can't solve this problem. As you know, he's really weak at graph theory; so try to help him in solving the problem. You are

Codeforces Round #363 Div.2[11110]

好久没做手生了,不然前四道都是能A的,当然,正常发挥也是菜. A:Launch of Collider 题意:20万个点排在一条直线上,其坐标均为偶数.从某一时刻开始向左或向右运动,速度为每秒1个单位长度.输入给出每个点的坐标及其移动的方向,求发生第一次碰撞的时间,若不会碰撞,则输出-1 最先发生碰撞的是一定是初始时相邻的两个点,因此只需对每个点循环一边,判断其是否会与下一个点碰撞,并求出其时间即可. #include<stdio.h> #include<stdlib.h> int

Codeforces Round #536 (Div. 2) E dp + set

https://codeforces.com/contest/1106/problem/E 题意 一共有k个红包,每个红包在\([s_i,t_i]\)时间可以领取,假如领取了第i个红包,那么在\(d_i\)后才能领取下一个红包,每个红包价值\(w_i\),对方假如有机会领取红包他一定会领取,你有m次阻止对方领取的机会,问对方最少可以拿到多少红包 题解 定义dp[i][j]为前i秒用了j次机会让对方拿到最小价值的红包 \(dp[i][j] - > dp[i+1][j+1]\) 假如使用阻止 \(d

Codeforces Round #548 (Div. 2) C dp or 排列组合

https://codeforces.com/contest/1139/problem/C 题意 一颗有n个点的树,需要挑选出k个点组成序列(可重复),按照序列的顺序遍历树,假如经过黑色的边,那么这个序列就是好的,问有多少个好的序列 题解 黑边不连,红边连,假如两个点不在同一并查集,那么一定经过黑边 定义\(dp[i][j][k]\)为选择前i个点,起始点为j,是否已经经过黑边(k)的方案数 \(dp[i-1][j][0]*(n-N[fin(j)])+dp[i-1][j][1]*n - > dp

Codeforces Round #156 (Div. 1)A dp

//对每个数进行一个编号, //dp[i][j]表示第i个数其前面是第j个数得到的最长子序列 //dp[i][j] =  dp[i][j] = dp[last[j]][map[num[i]]] + 1; //last[j]是编号为j的数的最后出现的位置 //map[num[i]]第i个数的编号 #include<iostream> #include<cstdio> #include<cstring> using namespace std ; const int max

Codeforces Round #144 (Div. 1) B dp

//第i列和第i+n的涂色个数是相同的,所以只需要处理前n列 //dp[i][j]表示前i列有j个涂色的方法数 //dp[i][j] += dp[i-1][s]*pow(c[n][s] , m/n) //c[n][s] 表示从n个数中取s的组合数 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 110 ; const __int64

CodeForces 698A - Vacations (Codeforces Round #363 (Div. 2))

要么去体育馆,要么去比赛,要么闲在家里 给出每一天体育馆和比赛的有无情况,要求连续两天不能去同一个地方 问最少闲几天 DP方程很容易看出 dp(第i天能去的地方) = min(dp(第i-1天的三种情况)) : dp(第i天呆在家里) = min(dp(第i-1天的三种情况))+1: 1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 #define inf 0x3f3f3f3f 5 int a[10

Codeforces Round #162 (Div. 1) B dp

//存入所有数的素数因数 //若两个数不互质,那么他们之间必然有素数因数 //dp[i][0]表示第i个数不选前i个数中能得到的最长序列 //dp[i][1]表示选了第i个数 //dp[i][0] = max(dp[i-1][0] , dp[i-1][1]) //dp[i][1] = max(dp[pos][1] + 1 ,dp[i][1] ); //pos位第i个数的质数因子出现的最后一个位置 #include<cstdio> #include<cstring> #include

Codeforces Round #363 (Div. 1) C. LRU

题意: n个数,长度为k的缓存,每次询问,每个数以pi的概率被选,如果不在缓存区则加入,如果缓存区满了,则第一个进缓存的出来,问10^100次询问以后每个数在缓存的概率 思路: 状压DP,看了hzwer的代码 f[x]表示当前状态为x的概率 枚举不在缓存区的数:f[t]+=f[x]*(p[i]/tot);  t=x|(1<<(i-1)); tot是当前状态情况下,不在缓存区的所有概率 如果缓存区数大于k,则当前状态概率为0 1 // #pragma comment(linker, "