问题描述:

  娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题。
  她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女生。
  娜娜学习确实很神,但是她在琦琦面前却总是表现不出平时的神力。
  琦琦感受到了娜娜对他的爱,但是他还是觉得娜娜的学习并不是特别好,于是他出了一道题给娜娜。
  “娜娜,我们之间的关系需要在不断深入的同时保持一定的平衡,不可以你总是强势或者我总是弱势。”
  琦琦给了娜娜一些两两不等的数,希望娜娜能把这些数分成两组A和B,满足以下条件:
  1:每一次只能操作一个数,即只取出一个数分入A中或B中;
  2:每一次操作完成后,A中数之和与B中数之和的差不能超过r。

  新时代的丘比特们啊,帮帮娜娜吧!

输入格式:

  输入共两行。
  第一行包括两个正整数n和r,n表示琦琦一共给了n个数,r的意义见题目描述。
  第二行包括n个正整数,分别表示琦琦给的n个数。

输出格式:

  输出共两行,分别把A与B两组数按从小到大输出。
  注意输入中n个数的第一个必须分入A组。
  琦琦保证这样的输出唯一。

样例输入:

4 10
9 6 4 20

样例输出:

4 6 9
20

样例说明:

  先把4和6先后分入A组,再把20分入B组,最后把9分入A组。

数据规模和约定:

  很小,真的很小。


前言(上):

我一开始的解题思路是:不断加入新数据的同时,时刻保持"两人"平衡。

有新数据,能加给"娜娜"便直接加,不然加给"琦琦"。

"两人"平衡则继续等新数据,不然必是"琦琦强于娜娜",则重复"琦琦"中找出最小的元素"娜娜",直到"两人"再次平衡……

但最多只有80%的正确率,上网搜索了一下,发现可能是 有些测试样例答案不唯一。

(我是在蓝桥杯官网写的题目,没有测试样例可以查看,所以也不确定)

(之后等我发现哪些样例答案不唯一的时候,再回来指出)

(敲代码时就有一种感觉,本题不应该只是让你(随随便便)将数据搬来搬去,要用到算法才正常)


前言(下):

参考文章:蓝桥杯 算法训练 娜神平衡_陆小路-1的博客-CSDN博客

然后找到 我觉得 是解这道题的文章 里面最好的一篇(上面这篇)。

有详细注释!!!(第一次看代码就懂怎么解题,少走了弯路)

强烈建议没有看过的同学先去看看。

接下来,我只着重讲一下"算法"方面的内容,即上面这篇文章中用到的 递归 是如何进行解题的。


开始:

我修改后的代码:(方便理解:去除了容器vector,减少了一些函数的参数<=>用全局变量代替)

#include<iostream>
using namespace std;
#include<algorithm>//数量n,限制r
int n, r;//左堆,左堆数量
int L[101] = { 0 }; int L_ = 0;
//右堆,右堆数量
int R[101] = { 0 }; int R_ = 0;//原始数据
int date[101] = { 0 };
//标记对应数据状态:已选 或 未选
bool ind[101] = { 0 };//打印数组 - 无回车
void print(int ii[], int n)
{for (int i = 1; i <= n; i++)cout << ii[i] << " ";return;
}//递归调用
bool func(int L_R = 0)
{//差值(绝对值)int temp = L_R > 0 ? L_R : -L_R;//若绝对值超出,则结束(注意temp不要去绝对值啊)if (temp > r){return false;}//当所有数据都能用上时 - 就代表可以结束了if (L_ + R_ == n){//排序 - 升序sort(L + 1, L + L_);sort(R + 1, R + R_);//寻找第一个数据for (int i = 1; i <= L_; i++){if (date[1] == L[i]){print(L, L_);cout << endl;print(R, R_);return true;}}print(R, R_);cout << endl;print(L, L_);return true;}int i;for (i = 1; i <= n; i++){//检查状态:若没有使用(false)if (!ind[i]){//标记为已使用(true)ind[i] = true;//加给左堆L[++L_] = date[i];//选定之后,往后继续if (func(L_R + date[i]))break;//取出L[L_] = 0;L_--;//加给右堆R[++R_] = date[i];//选定之后,往后继续if (func(L_R - date[i]))break;//取出R[R_] = 0;R_--;//就当无事发生ind[i] = false;}}//若能走到这里,i能到n:返回1;i没到n,返回0//告诉上层的判断:该层及其以下 递归能不能遍历完 所有的元素return !(i == n + 1);
}int main()
{cin >> n >> r;//输入数据for (int i = 1; i <= n; i++)cin >> date[i];//开始递归func();return 0;
}

以下是程序运行时的截图(运行时可以自己设置断点,定下标记来查看,不需要的自行跳过)

测试数据:n = 4 , r = 10 , date : 9 6 4 20

        初始左右两堆为0

        选9放入左堆

        选6放入左堆(但超出r,下一步更改选择)

         选6放入右堆

        选4放入左堆

         选20放入左堆(超出r,下一步更改选择)

        选20放入右堆(也超出r,下一步回溯

        选4放入右堆

        选20放入左堆(超出r,下一步更改选择)

         选20放入右堆(也超出r,下一步回溯

 上一步选4,这步跳过,直接选20放入左堆(超出)

         选20放入右堆(也超出r,下一步回溯

        注意:4回溯完以后,就到6了。并且6放右堆也做完了,所以这步是跳过6,再次选4放左堆(但是超出r,下一步重选)

         选4放入右堆

        注意:每次选数字都是从"左到右",选未被选过的数字,所以在4放入右堆之后,下一个选择的数字是6,6放入左堆(还是超出,下一步重选)

        选6放入右堆

        选20放入左堆(超出r,下一步更改选择)

        选20放入右堆(也超出r,下一步回溯

 注意:这次回溯6,下一个到20。选20放入左堆

        一样,再选20放入右堆

 这次4(左右堆都选了)这次只能再放弃,则到20注意:可能这里有同学有疑惑了,这次放弃了4,未选的不是有620吗?从左到右的话(9 6 4 20),不应该选6么?但请注意:从左到右是 基于 新的递归/当前位置 。意思是说,虽然是从左到右,但是每个递归函数内部是有一个for循环的,且控制到那个数字的i是++的,即4不选,下一个应该是4后面的20,不是6,除非又到的下一层递归,i重头开始……(不懂也没什么关系,继续往下)所以:选20放入左堆

        选20放入右堆

 选9入左堆的所有情况都完了,现在该选9放入右堆

        选6放入左堆

        选4放入左堆

        选20放入左堆

        选20放入右堆

         选4放入右堆

        选20放入左堆

        选20放入右堆

        放弃4, 选20放入左堆

        选20放入右堆

        选6放入右堆

        放弃6, 选4放入左堆

        选6放入左堆

        选20放入左堆

        选20放入右堆

        选6放入右堆

        放弃6,选20放入左堆

        选20放入右堆

        选4放入右堆

        放弃4,选20放入左堆

        选20放入右堆

        放弃9,选6放入左堆

        选9放入左堆

        选9放入右堆

        选4放入左堆

        选20放入左堆

        选20放入右堆

        选4放入右堆

        选20放入左堆

        选20放入右堆

        放弃4,选20放入左堆

        选20放入右堆

         放弃9,选4放入左堆

        选9放入左堆

        选9放入右堆

        选20放入左堆

        选20放入右堆

        放弃9,选20放入左堆

        选20放入右堆

        选9放入左堆
呼~~~终于结束了,62张图啊。


总结起来就是:

每层递归函数都会进行一个操作(对一个数字放左堆/右堆放弃),并且该层递归会遍历所有数字。

值得注意的是:

每层递归函数内的循环都是从头开始,而保存原始数据/左右堆的数据又可以随时改变(去下层时可更新数据,返回上层递归时又会清除数据恢复到去下层递归之前的状态……)

然后:

若无中间符合条件导致递归终止,其会枚举(若干数字的)所有组合情况。

只不过加了一些判断条件可以完成题意。


结束:

嗯,不难,看过我之前的《无聊的逗》或者学过深搜算法的同学理解起来应该没问题。

个人感觉跟DFS没太大区别,核心思想差不多……

(唉~就应该用这样的思路去解题的,不然最高才80%)

希望理解吧。

蓝桥杯 试题 算法训练 娜神平衡 C++ 详解相关推荐

  1. 蓝桥杯 试题 算法训练 娜神平衡Java

    资源限制 时间限制:1.0s   内存限制:256.0MB 问题描述 娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题. 她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女 ...

  2. 蓝桥杯 试题 算法训练 娜神平衡 java实现

    问题描述 娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题. 她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女生. 娜娜学习确实很神,但是她在琦琦面前却总是表现不出平时的 ...

  3. 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解

    题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...

  4. 蓝桥杯 试题 算法训练 无聊的逗 C++ 详解 - 未完善

    题目: 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的 ...

  5. 试题 算法训练 娜神平衡

    问题描述 娜娜是一个特别可爱的女孩子,作为学神的她最近在情感方面出现了一点点小问题. 她暗恋的琦琦是一名学霸,他只喜欢长得漂亮和学习很好的女生. 娜娜学习确实很神,但是她在琦琦面前却总是表现不出平时的 ...

  6. 蓝桥杯 试题 算法训练 筛选号码 Java

    蓝桥杯 试题 算法训练 筛选号码Java 算法训练 筛选号码 资源限制 时间限制:1.0s 内存限制:512.0MB 问题描述 有n个人围成一圈,顺序排号(编号为1到n).从第1个人开始报数(从1到3 ...

  7. 蓝桥杯 试题 算法训练 无聊的逗

    蓝桥杯 试题 算法训练 无聊的逗 问题描述 逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中.不过他想到了一个游戏来使他更无聊.他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘 ...

  8. 蓝桥杯试题 算法训练 绘制地图

    蓝桥杯试题 算法训练 绘制地图 问题描述 最近,WYF正准备参观他的点卡工厂.WYF集团的经理氰垃圾需要帮助WYF设计参"观"路线.现在,氰垃圾知道一下几件事情: 1.WYF的点卡 ...

  9. 蓝桥杯 试题 算法训练 24点 C++ 详解

    问题描述: 24点游戏是一个非常有意思的游戏,很流行,玩法很简单:给你4张牌,每张牌上有数字(其中A代表1,J代表11,Q代表12,K代表13),你可以利用数学中的加.减.乘.除以及括号想办法得到24 ...

最新文章

  1. java list键值_java基础之对List,Map,Set等集合键值对的简单认识
  2. 港中文提出全新点云上采样方法,破解自动驾驶感知难题
  3. java的并发框架_java并发框架有哪些
  4. 成功解决AttributeError: ‘NoneType‘ object has no attribute ‘shape‘
  5. php中post,php中post的用法是什么
  6. java this.name= name_thread(this, ThreadName)对于Java中这个语句,this是什么?
  7. (转)linux下vi编辑器编写C语言的配置
  8. ON_COMMAND和ON_MESSAGE的区别
  9. Java JSON转换为map
  10. CAD中如何使用Lisp程序编写坐标标注功能
  11. 单点登录CAS-01:如何找到适合自己JDK版本的CAS?
  12. 锐捷服务器虚拟化技术_2019云计算分类排行发布 星网锐捷勇夺两项榜首
  13. word打开wps文件乱码_word文件打不开,打开时遇到错误用文本修复器打开文件 WPS打开时是乱码...
  14. 无法安装64位版本的Office,因为在您的PC上找到了以下32位程序……解决办法
  15. Exploratory Data Analysis可视化分析美国天气
  16. AlphaFold2: Highly accurate protein structure prediction with AlphaFold笔记
  17. PSO算法文献阅读笔记
  18. 下载chromedriver
  19. Windows系统被faust勒索病毒攻击勒索病毒解密服务器与数据库解密恢复
  20. 发票扫描仪的正确打开方式

热门文章

  1. 【目标跟踪: 相关滤波器 三】循环矩阵
  2. 【唯选壁纸】UNIAPP云开发的壁纸类运营小程序、多端适配、创作者系统可运营
  3. html中input只读属性readonly 和 disable的区别
  4. xynuoj 均分纸牌问题 酒馆浪人的博客
  5. 智能科技对家居生活的影响,未来智能家居的发展方向
  6. 为什么这些脑残应用能活,而那些严肃牛逼的应用死了?
  7. 万国觉醒迁服务器显示该王国还未开放,万国觉醒无法迁城怎么办 王国迁城条件及详细步骤...
  8. crc16的c语言函数 计算ccitt_CCITT CRC-16计算原理与实现
  9. php 删除 确认,js确认删除方法 js删除确认提示框
  10. 项目中css的初始化