在TechFlow学长的公众号里发现一道挺有意思的CF算法题,现在利用学长的思路学习一下

题目链接:https://codeforces.com/contest/1418/problem/C

题意

这道题的题意也很有意思,背景也是游戏。说是有一天你和你的基友一起在家打游戏,这个游戏一共有n个boss。这些boss的难度不同,有些boss简单,有些boss困难。你的技术要比基友的好一些,你们两人轮流打boss。

游戏规定每次进行游戏最少打1个boss,最多打两个boss。由于你的实力更好,你可以战胜所有的boss。但是你的基友比较菜,只能打得过简单的boss,如果碰上hard模式的boss就只能氪金。基友的钱也是钱,你们希望在尽量少氪金的前提下把游戏通关。现在已知所有boss的难易情况并且基友先开始游戏,请问在最佳策略下,最少需要氪金多少次?

样例

首先给定一个数字t,表示测试数据组数。对于每组数据,给定一个数字n,表示boss的数量。接着给定n个0或者1的整数,0表示boss是简单模式,1表示是困难模式。要求返回一个数字,即最少的氪金次数。其中

\[n≤2⋅10^5
\]
input:
8
1 0 1 1 0 1 1 1 output:
2

样例解释

基友先杀1和2两个boss,氪金一次。

“我”杀3和4号boss

基友杀5号boss

“我”杀6和7号boss

基友击杀8号boss,氪金一次,总共氪金两次。

题解

这道题我们最先想到的可能就是贪心,比如我们可以想到一种贪心策略,就是每次基友杀怪的时候先杀1个,然后看第二个是0还是1,如果是0的则一起杀了,否则不杀留给“我”。

我们可以用之前介绍过的等价判断法来判断一下这个贪心策略可不可行,对于这道题而言,贪心的本质是让氪金的次数最少。所以当基友的第二个怪是0的时候,杀和不杀对于当前的氪金次数来说是没有影响的。但是对于后面的局面是会有影响的,并且可能会出现不同的结果。

比如我们可以找到一个例子10011,基友杀不杀第二个怪,直接影响后面的结果。如果基友杀了,那么不论“我”怎么选,基友都必须要至少再氪金一次。如果基友不杀,那么“我”杀第二个怪,基友再杀第三个怪,最后两个boss都交给“我”,那么基友全局只需要氪金一次。所以贪心算法不可行。

动态规划

如果你熟悉动态规划的话,那么几乎可以发现这是一道经典的动态规划问题。对于每一个怪来说,它都有两种状态,分别是被基友杀或者是被“我”杀。我们用0和1来分别表示,0表示被基友杀,1表示被“我”杀。一共有n个怪,所以我们可以用一个n * 2的数组来记录所有怪的状态。

对于第i个怪而言,如果它是被“我”杀的,那么它可以由基友杀了i-1或者是i-2个怪的状态转移得到。比如如果从基友杀了i-1转移得到,说明“我”杀了i,否则说明“我”不仅杀了i,还杀了i-1。同理i被基友杀的情况也是一样,所以这个状态转移方程就非常明显了。

# 学长的Python解法,注释满满
import sys t = int(input()) for _ in range(t):
n = int(input())
arr = list(map(int, input().split(' ')))
dp = [[sys.maxsize, sys.maxsize] for _ in range(n+2)] dp[0][1] = 0 for i in range(1, n+1):
if i > 1:
# 如果i > 1,那么说明可以杀两个
# 0表示基友杀怪的情况,基友可以杀1个从i-1转移得到,也可以杀2个从i-2转移得到
# 需要加上氪金的次数
dp[i][0] = min(dp[i-1][1] + arr[i-1], dp[i-2][1] + arr[i-2] + arr[i-1])
# 我杀怪不用氪金,直接赋值即可
dp[i][1] = min(dp[i-1][0], dp[i-2][0])
else:
# i=1,那么只能杀一个
dp[i][0] = dp[i-1][1] + arr[i-1]
dp[i][1] = dp[i-1][0] print(min(dp[n][0], dp[n][1]))
// 蒟蒻C++解法
// Author : RioTian
// Time : 20/11/07
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int main() {
// freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int x, ans = 0, sum = 0;
n--;
cin >> ans;
while (n--) {
cin >> x;
if (x)
sum++;
else
ans += sum / 3, sum = 0;
}
cout << ans + sum / 3 << endl;
}
}

最后,这道题非常的基础,可以说是动态规划的基础问题了。如果对动态规划这个概念不是很熟悉的话,非常建议动手做一做,加深一下印象。

Codeforce算法题 | 你能想出解法,让你的基友少氪金吗?的更多相关文章

  1. LeetCode算法题-First Bad Version(Java实现-三种解法)

    这是悦乐书的第200次更新,第210篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第66题(顺位题号是278).您是产品经理,目前领导团队开发新产品.不幸的是,您产品的最 ...

  2. LeetCode算法题-Longest Palindrome(五种解法)

    这是悦乐书的第220次更新,第232篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第87题(顺位题号是409).给定一个由小写或大写字母组成的字符串,找到可以用这些字母构 ...

  3. LeetCode算法题-Find the Difference(Java实现-五种解法)

    这是悦乐书的第214次更新,第227篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第82题(顺位题号是389).给定两个字符串s和t,它们只包含小写字母.字符串t由随机混 ...

  4. LeetCode算法题-Reverse Vowels of a String(Java实现-四种解法)

    这是悦乐书的第206次更新,第218篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第74题(顺位题号是345).编写一个函数,它将一个字符串作为输入,并仅反转一个字符串的 ...

  5. LeetCode算法题-Missing Number(Java实现-四种解法)

    这是悦乐书的第200次更新,第209篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第65题(顺位题号是268).给定一个包含n个不同数字的数组,取自0,1,2,...,n ...

  6. LeetCode算法题-Add Digits(Java实现-3种解法)

    这是悦乐书的第199次更新,第207篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第63题(顺位题号是258).给定非负整数num,重复添加其所有数字,直到结果只有一位数 ...

  7. LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)

    这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个 ...

  8. LeetCode算法题-Number Complement(Java实现-五种解法)

    这是悦乐书的第240次更新,第253篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第107题(顺位题号是476).给定正整数,输出其补码数.补充策略是翻转其二进制表示的位 ...

  9. LeetCode算法题-Third Maximum Number(Java实现-四种解法)

    这是悦乐书的第222次更新,第235篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第89题(顺位题号是414).给定非空的整数数组,返回此数组中的第三个最大数字.如果不存 ...

随机推荐

  1. 087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点

    087 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 01 封装的概念和特点 本文知识点:封装的概念和特点 说明:因为时间紧张,本人写博客过程中只是对 ...

  2. Java知识系统回顾整理01基础06数组05复制数组

    数组的长度是不可变的,一旦分配好空间,是多长,就多长,不能增加也不能减少 一.复制数组 把一个数组的值,复制到另一个数组中 System.arraycopy(src, srcPos, dest, de ...

  3. 在Python中使用OpenCV(CV2)对图像进行边缘检测

    转载:https://blog.csdn.net/cumtb2002/article/details/107798767 Modules used: 使用的模块: For this, we will ...

  4. SetDlgItemText()与UpdateData()的区别

    转载:https://blog.csdn.net/qq_20161893/article/details/72818874 SetDlgItemText(IDC_EDIT_RXDATA,m_strRE ...

  5. ASP。NET Core Blazor CRUD使用实体框架和Web API

    下载source code - 1.7 MB 介绍 *请查看我的Youtube视频链接来学习ASP.NET Core Blazor CRUD使用实体框架和Web API. 在本文中,我们将了解如何为A ...

  6. 这就是小学生也会用的四则计算练习APP吗?- by软工结对编程项目作业

    结对编程项目 软件工程 这就是链接 作业要求 这就是链接 作业目标 熟悉在未结对情况下如何结对开发项目 Github与合作者 合作者(学号): 区德明:318005422 虚左以待 Github链接: ...

  7. redis哨兵搭建

    redis哨兵搭建 1.复制配置文件到conf #单机安装以后[root@t3 redis-5.0.8]# pwd/app/redis-5.0.8[root@t3 redis-5.0.8]# cp s ...

  8. 将本地代码初始化上传到gitlab仓库

    首先你已经安装了git. 1.在本地代码目录,鼠标右键Git Bash Here: 2.执行git命令,此命令会在当前目录下创建一个.git文件夹, git init 3.将项目的所有文件添加到仓库中 ...

  9. linux CentOS7 防火墙操作

    1, 查看防火墙状态: firewall-cmd --state systemctl status firewalld.service 2, 开启防火墙: systemctl start firewa ...

  10. 多测师讲解python _练习题002_高级讲师肖sir

    # 1.求出1/1+1/3+1/5--+1/99的和 # 2.用循环语句,计算2-10之间整数的循环相乘的值. # 3.用for循环打印九九乘法表 # 4.求每个字符串中字符出现的个数如:hellow ...