天梯赛 L2-047 锦标赛

原题链接:

PTA | 程序设计类实验辅助教学平台

题面:

有 2k 名选手将要参加一场锦标赛。锦标赛共有 k 轮,其中第 i 轮的比赛共有 2k−i 场,每场比赛恰有两名选手参加并从中产生一名胜者。每场比赛的安排如下:

  • 对于第 1 轮的第 j 场比赛,由第 (2j−1) 名选手对抗第 2j 名选手。
  • 对于第 i 轮的第 j 场比赛(i>1),由第 (i−1) 轮第 (2j−1) 场比赛的胜者对抗第 (i−1) 轮第 2j 场比赛的胜者。

第 k 轮唯一一场比赛的胜者就是整个锦标赛的最终胜者。
举个例子,假如共有 8 名选手参加锦标赛,则比赛的安排如下:

  • 第 1 轮共 4 场比赛:选手 1 vs 选手 2,选手 3 vs 选手 4,选手 5 vs 选手 6,选手 7 vs 选手 8。
  • 第 2 轮共 2 场比赛:第 1 轮第 1 场的胜者 vs 第 1 轮第 2 场的胜者,第 1 轮第 3 场的胜者 vs 第 1 轮第 4 场的胜者。
  • 第 3 轮共 1 场比赛:第 2 轮第 1 场的胜者 vs 第 2 轮第 2 场的胜者。

已知每一名选手都有一个能力值,其中第 i 名选手的能力值为 ai​。在一场比赛中,若两名选手的能力值不同,则能力值较大的选手一定会打败能力值较小的选手;若两名选手的能力值相同,则两名选手都有可能成为胜者。

令 li,j​ 表示第 i 轮第 j 场比赛 败者 的能力值,令 w 表示整个锦标赛最终胜者的能力值。给定所有满足 1≤i≤k 且 1≤j≤2k−i 的 li,j​ 以及 w,请还原出 a1​,a2​,⋯,an​。

输入格式:

第一行输入一个整数 k(1≤k≤18)表示锦标赛的轮数。
对于接下来 k 行,第 i 行输入 2k−i 个整数 li,1​,li,2​,⋯,li,2k−i​(1≤li,j​≤109),其中 li,j​ 表示第 i 轮第 j 场比赛 败者 的能力值。
接下来一行输入一个整数 w(1≤w≤109)表示锦标赛最终胜者的能力值。

输出格式:

输出一行 n 个由单个空格分隔的整数 a1​,a2​,⋯,an​,其中 ai​ 表示第 i 名选手的能力值。如果有多种合法答案,请输出任意一种。如果无法还原出能够满足输入数据的答案,输出一行 No Solution
请勿在行末输出多余空格。

输入样例1:

3
4 5 8 5
7 6
8
9

输出样例1:

7 4 8 5 9 8 6 5

输入样例2:

2
5 8
3
9

输出样例2:

No Solution

提示:

本题返回结果若为格式错误均可视为答案错误

解题思路:

本质上是一个灵活使用完全二叉树的题目。

每个节点存储一场比赛的胜负者能力值:

struct node {int win;int lose;
} tree[1 << 20];

因为是完全二叉树,所以我们不必使用动态存储方式,不必使用指针来实现,可以用数组实现,假设当前节点为tree[root],那么它的左子节点为tree[root * 2],右子节点为tree[root * 2 + 1]。

根节点存储决赛的胜负者,第二层节点存储第k-1轮的胜负者,第三层节点存储第k-2轮的胜负者,……最后一层节点存储第一轮的胜负者。

接收题目的输入之后,我们得到了每个节点的lose值,并且只有决赛也就是根节点的win和lose值是全部都已知的。

此时我们先进行一个特判,根节点如果lose值大于win值,则代表题目给出的数据是无解的。

然后要做的事情就是填写除了根节点以外的win值,因为会存在试错回溯的过程,所以很直观想到的解法就是递归。

递归函数为dfs(int root, int size);root为当前节点编号,size为二叉树的节点数量。

我们先设当前节点的两个子节点中,更强的败者所在的节点编号为bLoser,更弱的败者所在的节点编号为sLoser。

递归过程中我们用当前节点的win和lose去填充子节点的win,会出现以下几种情况:

(1)无解:如果当前节点的胜者弱于bLoser的败者,或者当前的败者弱于sLoser的败者,则证明这个解是错误的,需要回溯。

(2)有解:

        一种可能解:如果bLoser的败者强于当前节点的败者,那么当前节点的败者只能是sLoser的胜者,此时只有一种解,将当前节点的胜者填入bLoser,将当前节点的败者填入sLoser。

        两种可能解:此时两种填法都有可能成为正解,所以我们需要将两种解法都尝试一遍,如果第一种尝试是错误的,那么我们在递归返回之后需要尝试第二种,因为这里我们需要在第一种尝试完毕递归返回之后判断是否是错误解需要尝试另一种,所以我们需要开一个bool全局变量errFlag来记录。

光看上边的解释可能很复杂,很懵圈,具体实现见代码。

代码(CPP):

#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e3 + 10;
const int INF = 0x3fffffff;
const int mod = 1000000007;
struct node {int win;int lose;
} tree[1 << 20];
bool errFlag = false;void dfs(int root, int size) {// 递归边界:已经到叶子节点或者此时已经是错误解状态,可以提前返回if (root * 2 > size || errFlag) {return;}// 得到两个子节点的更强败者以及更弱败者int bLoser = (tree[root * 2].lose > tree[root * 2 + 1].lose ? root * 2 : root * 2 + 1);int sLoser = (tree[root * 2].lose < tree[root * 2 + 1].lose ? root * 2 : root * 2 + 1);// 如果当前的胜者弱于子节点更强的败者,或者当前的败者弱于子节点更弱的败者,则证明这个解是错误的if (tree[root].win < tree[bLoser].lose || tree[root].lose < tree[sLoser].lose) {errFlag = true;return;}// 判断if (tree[bLoser].lose > tree[root].lose) {// 如果子节点更强的败者强于当前节点的败者,那么当前节点的败者只能是另一个子节点的胜者,此时只有一种解tree[sLoser].win = tree[root].lose; // 当前的败者一定是从更弱的那边晋级上来的tree[bLoser].win = tree[root].win;  // 当前的胜者一定是从更强的那边晋级上来的dfs(root * 2, size);dfs(root * 2 + 1, size);} else {// 此时两种解都有可能,都要递归尝试一遍tree[sLoser].win = tree[root].lose;tree[bLoser].win = tree[root].win;dfs(root * 2, size);dfs(root * 2 + 1, size);if (errFlag) {errFlag = false;swap(tree[sLoser].win, tree[bLoser].win);dfs(root * 2, size);dfs(root * 2 + 1, size);}}
}void solve() {int k;cin >> k;int size = (2 << (k - 1)) - 1;// 输入每一轮每场比赛的败者能力值for (int i = k; i > 0; i--) {int n = (1 << (i - 1));int s = (2 << (i - 1)) - n;while (n--) {cin >> tree[s].lose;s++;}}// 输入最后的冠军能力值,如果冠军能力值低于亚军则证明这是无解的cin >> tree[1].win;if (tree[1].lose > tree[1].win) {errFlag = true;} else {dfs(1, size);   // 递归填写每一轮每场的胜者能力值}// 输出结果if (errFlag) {cout << "No Solution\n";} else {int n = (1 << (k - 1));int s = (2 << (k - 1)) - n;while (n--) {cout << tree[s].win << " " << tree[s].lose;s++;if (n)cout << " ";}}
}int main() {// freopen("in.txt", "r", stdin);ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cout << fixed;cout.precision(18);solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/149865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多对多的创建方式与Ajax

模型层补充 MTV与MVC模型 MTV 全称 Models Templates Views 模型模板视图 MVC 全称 Models Views Controller 模型视图控制MTV: Django号称是MTV模型 MVC: 其实django本质也是MVC 拓展: vue框架:MVVM模型choices参数(数据库字段设计常见) choices使用 class User(models.Mod…

ansible-playbook剧本实现wordpress上线

准备环境&#xff1a; 1.需要三台服务器&#xff1a;主机服务器&#xff08;(10.36.192.129&#xff09;、db服务器(10.36.192.131)&#xff0c;web服务器(10.36.192.130)&#xff0c;剧本都是写在主机服务器上。 2.主机服务器需要做ansible解析 vim /etc/ansible/hosts[web…

CICD 持续集成与持续交付——jenkins

部署 软件下载&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/ [rootcicd2 ~]# rpm -ivh jdk-11.0.15_linux-x64_bin.rpm[rootcicd2 ~]# yum install -y fontconfig[rootcicd2 ~]# rpm -ivh jenkins-2.432-1.1.noarch.rpm启动服务 [rootcicd2 ~]# systemctl…

【JVM】Java虚拟机

本文主要介绍了JVM的内存区域划分,类加载机制以及垃圾回收机制. 其实JVM的初心,就是让java程序员不需要去了解JVM的细节,它把很多工作内部封装好了.但是学习JVM的内部原理有利于我们深入理解学习Java. 1.JVM的内存区域划分 JVM其实是一个java进程 ; 每个java进程,就是一个jvm…

MVSNet论文笔记

MVSNet论文笔记 摘要1 引言2 相关基础2.1 多视图立体视觉重建&#xff08;MVS Reconstruction&#xff09;2.2 基于学习的立体视觉&#xff08;Learned Stereo&#xff09;2.3 基于学习的多视图的立体视觉&#xff08;Learned MVS&#xff09; 3 MVSNet3.1 网络架构3.2 提取图片…

ModStartCMS v7.6.0 CMS备份恢复优化,主题开发文档更新

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

SAP ABAP结构与内表的创建

一、定义一个结构体 DATA:BEGIN OF LS_MATNR,MATNR TYPE MATNR,MAKTX TYPE MAKTX, END OF LS_MATNR. 二、定义一个包含表头的内表 DATA:BEGIN OF LT_MAT OCCURS 0,MATNR TYPE MATNR,MAKTX TYPE MAKTX, END OF LT_MAT. 三、参考数据结构来定义内表 DATA:LT_MAT LIKE TABLE…

OpenAI Assistants-API简明教程

OpenAI在11月6号的开发者大会上&#xff0c;除了公布了gpt4-v、gpt-4-turbo等新模型外&#xff0c;还有一个assistants-api&#xff0c;基于assistants-api开发者可以构建自己的AI助手&#xff0c;目前assistants-api有三类的工具可以用。首先就是之前大火的代码解释器(Code In…

苍穹外卖--菜品分页查询

设计DTO类 Data public class DishPageQueryDTO implements Serializable {private int page;private int pageSize;private String name;private Integer categoryId; //分类idprivate Integer status; //状态 0表示禁用 1表示启用}设计VO类 Data Builder NoArgsConstructor…

奇富科技发布鸿蒙元服务1.0版本,打造鸿蒙生态金融科技全新体验

近日&#xff0c;奇富科技率先发布鸿蒙元服务1.0版本&#xff0c;成为首家融入鸿蒙生态的金融科技公司&#xff0c;为用户带来前所未有的数字生活体验。此次与华为终端云的全面合作&#xff0c;是两大行业领军者的深度融合&#xff0c;不仅实现技术的交融&#xff0c;更彰显两大…

蓝桥杯 map

map 代码示例 #include<iostream> #include<map> using namespace std; int main(){//创建并初始化mapmap<int,string> myMap{{1,"Apple"},{2,"Banana"},{3,"Orange"}} ;//插入元素myMap.insert(make_pair(4,"Grapes&qu…

如何利用1688批发市场价格做跨境代购业务?(API数据接口)

随着互联网的快速发展&#xff0c;电子商务在全球范围内迅速普及。作为全球最大的B2B电子商务平台之一&#xff0c;1688为广大商家提供了一个便捷、高效的在线交易平台。在这个平台上&#xff0c;商家可以展示、售卖自己的产品&#xff0c;而消费者则可以轻松地找到心仪的商品。…

TensorRT基础知识及应用【学习笔记(十)】

这篇博客为修改过后的转载&#xff0c;因为没有转载链接&#xff0c;所以选了原创 文章目录 一、准备知识1.1 环境配置A. CUDA DriverB. CUDAC. cuDNND. TensorRT 1.2 编程模型 二、构建阶段2.1 创建网络定义2.2 配置参数2.3 生成Engine2.4 保存为模型文件2.5 释放资源 三、运…

ChatGPT API 学习

参考&#xff1a;从零开始的 ChatGPT API 使用指南&#xff0c;只需三步&#xff01; - 知乎 (zhihu.com) ChatGPT API 是一种由 OpenAI 提供的 API&#xff0c;它可以用最简单的方式把 ChatGPT 的聊天能力接入到各种应用程序或服务中。 自然语言语音识别(Natural Language S…

Kotlin原理+协程基本使用

协程概念 协程是Coroutine的中文简称&#xff0c;co表示协同、协作&#xff0c;routine表示程序。协程可以理解为多个互相协作的程序。协程是轻量级的线程&#xff0c;它的轻量体现在启动和切换&#xff0c;协程的启动不需要申请额外的堆栈空间&#xff1b;协程的切换发生在用…

云计算(一):弹性计算概述

云计算&#xff08;一&#xff09;&#xff1a;弹性计算概述 背景含义原理应用 背景 在实际场景中&#xff0c;经常会出现短时间内资源需求爆发式增长或长时间内资源需求不断增长&#xff0c;这时需要资源供给时刻满足需求的变化&#xff0c;保障业务正常运行。传统的供给方式…

为什么同样是做测试,别人年薪30W+?我10k!!!

作为一名初出茅庐的软件测试员&#xff0c;职业发展的道路的确蜿蜒曲折&#xff0c;面对一次次的岗位竞争&#xff0c;挑战一道道的面试关卡&#xff0c;一边带着疑惑&#xff0c;一边又要做出选择&#xff0c;只能无奈的感叹&#xff1a;比你优秀的人比你还努力&#xff0c;你…

图片降噪软件 Topaz DeNoise AI mac中文版功能

Topaz DeNoise AI for Mac是一款专业的Mac图片降噪软件。如果你有噪点的相片&#xff0c;可以通过AI智能的方式来处理掉噪点&#xff0c;让照片的噪点降到最 低。有了Topaz DeNoise AI mac版处理图片更方便&#xff0c;更简单。 Topaz DeNoise AI mac软件功能 无任何预约即可在…

“腾易视连”构建汽车生态新格局 星选计划赋能创作者价值提升

11月16日&#xff0c;在2023年广州国际车展前夕&#xff0c;以“腾易视连&#xff0c;入局视频号抓住增长新机会”为主题的腾易创作者大会在广州隆重举办。此次大会&#xff0c;邀请行业嘉宾、媒体伙伴、生态伙伴、视频号汽车领域原生达人等共济一堂&#xff0c;结合汽车行业数…

快速入门ESP32——开发环境配置PlatformIO IDE

相关文章 快速入门ESP32——开发环境配置Arduino IDE 快速入门ESP32——开发环境配置PlatformIO IDE 一、下载安装二、验证 一、下载安装 下载安装 vscode 安装PlatformIO插件 创建工程 二、验证 写一个简单的函数来验证一下功能 void setup() {// put your setup cod…