Educational Codeforces Round 95 (Rated for Div. 2)C. Mortal Kombat Tower(状态机dp)

题目描述

You and your friend are playing the game Mortal Kombat XI. You are trying to pass a challenge tower. There are n bosses in this tower, numbered from 1 to n. The type of the i-th boss is ai. If the i-th boss is easy then its type is ai=0, otherwise this boss is hard and its type is ai=1.
During one session, either you or your friend can kill one or two bosses (neither you nor your friend can skip the session, so the minimum number of bosses killed during one session is at least one). After your friend session, your session begins, then again your friend session begins, your session begins, and so on. The first session is your friend’s session.
Your friend needs to get good because he can’t actually kill hard bosses. To kill them, he uses skip points. One skip point can be used to kill one hard boss.
Your task is to find the minimum number of skip points your friend needs to use so you and your friend kill all n bosses in the given order.
For example: suppose n=8, a=[1,0,1,1,0,1,1,1]. Then the best course of action is the following:
your friend kills two first bosses, using one skip point for the first boss;
you kill the third and the fourth bosses;
your friend kills the fifth boss;
you kill the sixth and the seventh bosses;
your friend kills the last boss, using one skip point, so the tower is completed using two skip points.
You have to answer t independent test cases.

Input

The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.
The first line of the test case contains one integer n (1≤n≤2⋅105) — the number of bosses. The second line of the test case contains n integers a1,a2,…,an (0≤ai≤1), where ai is the type of the i-th boss.
It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output

For each test case, print the answer: the minimum number of skip points your friend needs to use so you and your friend kill all n bosses in the given order.

Example

input
6
8
1 0 1 1 0 1 1 1
5
1 1 1 1 0
7
1 1 1 1 0 0 1
6
1 1 1 1 1 1
1
1
1
0
output
2
2
2
2
1
0

题目大意

有n个怪物,a[i]=1表示第i个怪物较强,a[i]=0表示第i个怪物较弱。
你和你的朋友要去打这n个怪物,你们每次可以选择打1-2个怪物(你的朋友先打)。但你的朋友比较弱,打不过强的怪物,如果要打败强的怪物就要使用一个道具。
问需要消耗的最少道具数是多少。

题目分析

你和你的朋友每次选择不同的打怪数,使得最后消耗的道具最少。很明显这是一道dp问题。
又因为你打怪和你朋友打怪是两个不同的状态,因此要用到状态机dp。

  1. 状态表示f[i][0] //表示打完第i个怪物需要消耗的最少道具数,且最后一次战斗是由朋友完成的。
    f[i][1] //表示打完第i个怪物需要消耗的最少道具数,且最后一次战斗是由你完成的。
  2. 状态计算
    f[i][0]这个状态可以由f[i-1][1]和f[i-2][1]这两个状态转移而来。你朋友完成的最后一次战斗,因此上上次战斗是由你完成的,在战斗中你可以选择打1-2个怪.(f[i][0]=min(f[i-1][1]+a[i],f[i-2][1]+a[i-1]+a[i]))
    f[i][1]这个状态可以由f[i-1][0]和f[i-2][0]这两个状态转移而来。(f[i][1]=min(f[i-1][0],f[i-2][0]))
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=2e5+5,INF=0x3f3f3f3f;
int a[N],f[N][2];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		memset(f,INF,sizeof f);		//初始化
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		
		f[1][0]=a[1];			//i=1和i=2情况特殊,单独讨论
		f[2][0]=f[1][0]+a[2];
		f[2][1]=f[1][0];
		for(int i=3;i<=n;i++)	//dp过程
		{
			f[i][0]=min(f[i-1][1]+a[i],f[i-2][1]+a[i-1]+a[i]);
			f[i][1]=min(f[i-1][0],f[i-2][0]);
		}
		printf("%d\n",min(f[n][1],f[n][0]));	//答案为f[n][1]和f[n][0]中的最小值
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值