欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C. Mortal Kombat Tower(动态规划)Educational Codeforces Round 95 (Rated for Div. 2)

程序员文章站 2022-06-05 07:58:35
...

原题链接: http://codeforces.com/contest/1418/problems

C. Mortal Kombat Tower(动态规划)Educational Codeforces Round 95 (Rated for Div. 2)
测试样例

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 n n层,每层都有一个BOSS,它们都具有困难程度。现在你和你的朋友联手闯关,你们都可以杀死一个或两个BOSS(杀死两个BOSS即过两关。),当你的朋友结束关卡之后,你开始下一关,接下来再你朋友进行下一关。但有一个秘密:你的朋友其实无法杀死困难程度高的BOSS,他需要使用跳跃卡。问你们通过后他至少需要使用的跳跃卡数量。

解题思路: 一道经典的dp问题。我们要找准状态,由于每一关都是层层递进的,且每一关的通关者可以是你或者你朋友。(第一关除外。)那么我们则可以用01变量来表示你朋友和你。则我们就可以找到状态了:

  • d p [ i ] [ 0 ] dp[i][0] dp[i][0]表示通第 i i i关需要使用的最少通关卡,且第 i i i关为你朋友通关。
  • d p [ i ] [ 1 ] dp[i][1] dp[i][1]表示通关第 i i i关需要使用的最少通关卡,且第 i i i关为你通关。

找准状态之后根据题意设立状态转移方程即可(一定是根据题意来建立的),OK,具体看代码。

AC代码

/*
*邮箱:aaa@qq.com
*blog:https://me.csdn.net/hzf0701
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*
*/
#include<bits/stdc++.h>	//POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 2e5+5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll>  pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

int t,n,a[maxn];
int dp[maxn][2];//用0表示你朋友,1表示你自己。状态转移:用dp[i][0]表示打的第i个怪,且是你朋友打完的。dp[i][1]表示打的第i个怪,且是你打完的。
int main(){
	//freopen("in.txt", "r", stdin);//提交的时候要注释掉
	IOS;
	while(cin>>t){
        while(t--){
            cin>>n;
            rep(i,1,n){
                cin>>a[i];
            }
            //初始化
            memset(dp,inf,sizeof(dp));
            //确定特殊情况。
            dp[1][0]=a[1];
            dp[2][0]=dp[1][0]+a[2];
            dp[2][1]=dp[1][0];
            rep(i,3,n){
                //利用dp求解最小值。
                dp[i][0]=min(dp[i-1][1]+a[i],dp[i-2][1]+a[i-1]+a[i]);
                dp[i][1]=min(dp[i-1][0],dp[i-2][0]);
            }
            //最终状态有两个,求最小值即可。
            cout<<min(dp[n][0],dp[n][1])<<endl;
        }
	}
	return 0;
}