当前位置: 首页 > news >正文

15. 卡牌游戏

目录

题目

思路

C++整体代码(含详细注释)


题目

Description
小张在玩一种卡牌游戏,牌组由张牌组成,其中张上写有数字各一张,其余张上全部是数字。
现在牌组经过随机打乱后,小张拿走其中张牌作为手牌,其余张牌作为牌堆。
小张想经过若干次如下操作使得牌堆自顶向下的牌依次为。
每一次操作,小张选择任意一张手牌放到牌堆底,并将牌堆顶的牌放入手牌。
他想知道最少进行几次操作,使得牌堆自顶向下的牌依次为。
Input
第一行一个数。
第二行个数,表示小张手中的牌。
第三行个数,表示牌堆,数组从左向右的顺序表示牌堆自顶向下的顺序。
Output
一个整数,表示最少执行的操作数

测试输入期待的输出时间限制内存限制额外进程
测试用例 1以文本方式显示
  1. 3↵
  2. 0 2 0↵
  3. 3 0 1↵
以文本方式显示
  1. 2↵
1秒64M0
测试用例 2以文本方式显示
  1. 3↵
  2. 0 2 0↵
  3. 1 0 3↵
以文本方式显示
  1. 4↵
1秒64M0

思路

手上的牌不重要,重要的是牌堆里非0数字的位置,有三种情况:

1)牌堆最后存在1开头连续的数并且其他的数字均符合位置条件

2)牌堆最后存在1开头连续的数但其他的数字不均符合位置条件

3)牌堆最后不存在1开头连续的数

操作方法

  • 情况1的操作方式一目了然,直接把1前面的数字挤掉的同时在牌堆尾部添加相应的数字。
    结果=1的位置-牌堆顶部位置
  • 情况2和情况3虽然描述不同,但操作方法是一样的。
    结果=牌堆所有数字位置合理时需要操作的最大值+牌堆数字个数

具体步骤

1.定义一个函数hasSequentialSegment用于判断牌堆底部是否有以1开头的连续递增子序列。它通过遍历牌堆底部,找到1的位置,然后判断后续的数字是否连续递增,如果是则返回true,否则返回false。

// 判断牌堆底部是否有1开头的连续的子序列
bool hasSequentialSegment(const vector<int>& pile) {int k = 0;int num = 2;for (int i = 1; i < pile.size(); i++) {//找到1的位置if (pile[i] == 1) {k = i+1;break;}
}while (pile[k] == num) {//判断是否连续num++;k++;}//如果子序列从1开始连续递增直至牌堆底部,则返回trueif (k == pile.size()) return true;return false;//没有则返回false
}

2.定义一个函数calculateResult用于计算最少执行的操作数。首先判断牌堆底部是否有以1开头的连续递增子序列,如果有,再判断牌堆其他数字的位置是否满足条件。如果满足条件(情况一),则结果为1的位置减去牌堆顶部位置。如果不满足条件(情况二、三),则需要计算使牌堆所有数字位置合理时需要操作的最大值,即遍历牌堆中的数字,找到使数字位置合理的最大差值。最后,结果为牌堆所有数字位置合理时需要操作的最大值加上牌堆的数字个数。

// 计算最少执行的操作数
int calculateResult(const vector<int>& pile) {int result = 0;int maxDiff = 0;// 如果牌堆底部中包含1开头的连续的递增子序列if (hasSequentialSegment(pile)) {int k = 0;int target = 0;int flag = 1;//用于标记递增子序列以外的数字位置是否合理//找到1的位置for (int i = 1; i <= pile.size() - 1; i++) {if (pile[i] == 1) {k = i;break;}}target = pile.size() - k;//标记1开头连续子序列的最后一个数字for (int j = 1; j < k; j++) {//遍历1前面的数字,判断这个数字当前的位置是否合理if (pile[j] > target&& j + 1 > pile[j] - target) {flag = 0;//如果不合理,break;}}//计算操作次数,分为两种情况// 第一种情况:牌堆底部有1开头连续递增子序列且牌堆其他数字满足位置条件if (flag == 1) {result = k - 1;//结果=1的位置-牌堆顶部位置return result;}}//第二种情况:①牌堆底部没有1开头的递增子序列②牌堆底部有1开头的连续子序列但牌堆其他数字不满足位置条件// 计算使牌堆所有数字位置合理时需要操作的最大值for (int i = 1; i <= pile.size()-1; i++) {if (i >= pile[i] && pile[i] != 0) {maxDiff = max(maxDiff, i - pile[i] + 1);}}result = maxDiff + pile.size()-1;//结果=牌堆所有数字位置合理时需要操作的最大值+牌堆的数字个数return result;
}

3.在主函数中,首先读入输入的牌堆大小n,然后分别读入手牌和牌堆的数字。调用calculateResult函数计算最少执行的操作数,并输出结果。

int main() {int n;cin >> n;vector<int> hand(n + 1), pile(n + 1);for (int i = 1; i <= n; i++) {cin >> hand[i];}for (int i = 1; i <= n; i++) {cin >> pile[i];}int result = calculateResult( pile);cout << result << endl;return 0;
}

C++整体代码(含详细注释)

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 判断牌堆底部是否有1开头的连续的子序列
bool hasSequentialSegment(const vector<int>& pile) {int k = 0;int num = 2;for (int i = 1; i < pile.size(); i++) {//找到1的位置if (pile[i] == 1) {k = i+1;break;}
}while (pile[k] == num) {//判断是否连续num++;k++;}//如果子序列从1开始连续递增直至牌堆底部,则返回trueif (k == pile.size()) return true;return false;//没有则返回false
}// 计算最少执行的操作数
int calculateResult(const vector<int>& pile) {int result = 0;int maxDiff = 0;// 如果牌堆底部中包含1开头的连续的递增子序列if (hasSequentialSegment(pile)) {int k = 0;int target = 0;int flag = 1;//用于标记递增子序列以外的数字位置是否合理//找到1的位置for (int i = 1; i <= pile.size() - 1; i++) {if (pile[i] == 1) {k = i;break;}}target = pile.size() - k;//标记1开头连续子序列的最后一个数字for (int j = 1; j < k; j++) {//遍历1前面的数字,判断这个数字当前的位置是否合理if (pile[j] > target&& j + 1 > pile[j] - target) {flag = 0;//如果不合理,break;}}//计算操作次数,分为两种情况// 第一种情况:牌堆底部有1开头连续递增子序列且牌堆其他数字满足位置条件if (flag == 1) {result = k - 1;//结果=1的位置-牌堆顶部位置return result;}}//第二种情况:①牌堆底部没有1开头的递增子序列②牌堆底部有1开头的连续子序列但牌堆其他数字不满足位置条件// 计算使牌堆所有数字位置合理时需要操作的最大值for (int i = 1; i <= pile.size()-1; i++) {if (i >= pile[i] && pile[i] != 0) {maxDiff = max(maxDiff, i - pile[i] + 1);}}result = maxDiff + pile.size()-1;//结果=牌堆所有数字位置合理时需要操作的最大值+牌堆的数字个数return result;
}int main() {int n;cin >> n;vector<int> hand(n + 1), pile(n + 1);for (int i = 1; i <= n; i++) {cin >> hand[i];}for (int i = 1; i <= n; i++) {cin >> pile[i];}int result = calculateResult( pile);cout << result << endl;return 0;
}

http://www.lryc.cn/news/148238.html

相关文章:

  • vue使用打印组件print-js
  • 20230830比赛总结
  • DNS指向别名还是IP
  • 【考研数学】概率论与数理统计 —— 第二章 | 一维随机变量及其分布(1,基本概念与随机变量常见类型)
  • CSS判断手机暗黑模式
  • 【java中的Set集合】HashSet、LinkedHashSet、TreeSet(最通俗易懂版!!)
  • python中的文件操作
  • spark支持深度学习批量推理
  • 代码随想录打卡—day52—【子序列问题】— 8.31 最大子序列
  • gcc4.8.5升级到gcc4.9.2
  • Golang 中的 archive/zip 包详解(三):常用函数
  • 微服务架构七种模式
  • 关于CICD流水线的前端项目运行错误,npm项目环境配置时出现报错:Not Found - GET https://registry.npm...
  • element-plus的周选择器 一周从周一开始
  • Android 9.0 pms获取应用列表时过滤掉某些app功能实现
  • HTML <thead> 标签
  • 谷歌发布Gemini以5倍速击败GPT-4
  • 力扣92. 局部反转链表
  • 九、适配器模式
  • 使用spring自带的发布订阅来实现发布订阅
  • Walmart电商促销活动即将开始,如何做促销活动?需要注意什么?
  • Matlab(画图进阶)
  • 人生的回忆
  • Spring之依赖注入源码解析
  • 5G NR:RACH流程-- Msg1之生成PRACH Preamble
  • 高基数类别特征预处理:平均数编码 | 京东云技术团队
  • 高效利用隧道代理实现无阻塞数据采集
  • 图论岛屿问题DFS+BFS
  • Cypress web自动化windows环境npm安装Cypress
  • CentOS7.9设置ntp时间同步