持续更新蓝桥杯算法训练题解,有兴趣可以关注一波呀。

文章目录

  • 题目
  • 题解
  • 数据传送阵
  • 代码传送阵

题目

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.

题解

首先说一下,题目中的例子答案错了,应该是6, 5。当然以后可能会更新吧,但是现在是错的

题目的意思就是说:给定一个大小为n的集合,将集合划分成最多n - 1个子集合,使得每一部分的集合的元素和都相等。然后询问这样的

划分中,每一个集合的元素和最小是多少。

思路:暴力回溯。

首先,题目是有一些性质的:

  • 每一个集合的元素和,一定是总和的约数。划分后集合的元素和如果大于了总和的一半,那么只有一种可能,就是整个集合作为子集。

有了上面的性质,问题就转化成了:给定一个sum的约数k,判断集合是否可以将之划分成几个和恰好为k的子集合

这个题目可以参照1723. 完成所有工作的最短时间去做。但是这道题目的数据量更大,也就意味着,需要更加精确的剪枝代码。

剪枝的思路有以下几个,下面把元素形容成球,把集合当作桶:

  • 按照从大到小排序,这样可以更容易使得大的桶被放满。
  • 如果两个连续球相同,上一个装入本桶中没有答案,那么这个球装入桶中也不会有答案,可以直接返回。
  • 如果一个桶是空的,当前的放入不行,那么就没有桶行了。
  • 如果一个桶恰好装满了,没有答案,那么接下来也不会有答案,可以直接返回。

好有了上面的几条剪枝的规则,就可以随便A掉1773题目了,但是本题仍旧不行。因为数据是n <= 64,很大。所以还要想办法。

  • 记录当前遍历到了cur个球,如果cur+ a[i] < k,说明仍旧在使用当前的桶,并且前面的球已经不能用了,直接从cur + 1开始找下一个可以遍历的球。否则就是cur + a[i] == k,那么此时桶恰好装满了,需要从头开始找没有使用过的球。然后如果没答案可以直接返回(剪枝4)。

在实现的时候,使用sum表示当前桶中球的和,不用数组记录了,sum == 0的时候表示开启了一个新的桶。

数据传送阵

下面是没有记录当前球个数的代码,我只能说短小精悍。但是下面的一个数据会超时:

64
40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40
40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40
40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40
40
答案是:454

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <functional>
using namespace std;const int N = 100;
int a[N];
int n;
int vis[N];int check(int limit, int sum, int used) {if (used == n) return sum == 0;for (int i = 0; i < n; i++) {if (vis[i] || sum + a[i] > limit) continue;if (i && !vis[i - 1] && a[i] == a[i - 1]) continue;  // 剪枝2,相等的前不行,后一个也不行vis[i] = 1;if (check(limit, (sum + a[i]) % limit, used + 1))return true;vis[i] = 0;if (sum == 0 || limit == a[i]) break;              // 剪枝3,对于空桶来说,不用继续向下遍历了,第一个不行,后边都不行if (sum + a[i] == limit) break;                     // 剪枝4,如果有恰好装满的,仍及不行,直接break}return 0;
}int main() {while(scanf("%d",&n) != EOF && n) {int sum = 0;for (int i = 0; i < n; i++) {int b;scanf("%d", &b);a[i] = b;sum += b;}sort(a, a + n, greater<int>()); // 从大到小进行排序, 剪枝1int ans = sum;                   // 如果大于了sum/2就应该是sum,否则就是ifor (int i = a[0]; i <= sum / 2; i++) {memset(vis, 0, sizeof vis);if (sum % i != 0) continue; // 剪枝4, 如果不能整除肯定时不能作为长度的if (check(i, 0, 0)) {ans = i;break;}}printf("%d\n", ans);}return 0;
}

代码传送阵

增加球编号的代码如下,我只能说巧夺天工:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <functional>
using namespace std;const int N = 100;
int a[N];
int n;
int vis[N];
int check2(int cur, int sum, int used, int limit) {if (cur == n) return used == n;                 // 一旦用了n个,sum一定为0,因为是整除的if (used == n) return true;for (int i = cur; i < n; i++) {if (vis[i] || sum + a[i] > limit) continue;if (i && !vis[i - 1] && a[i] == a[i- 1]) continue; // 剪枝2if (sum + a[i] == limit) {vis[i] = 1;if (check2(0, 0, used + 1, limit)) return true; // 需要从头看是否还有没有用过的vis[i] = 0;                                      // 这里不要忘了回溯return false;                                   // 剪枝4, 如果恰好装满了,还是没答案,}else {vis[i] = 1;if (check2(i + 1, sum + a[i], used + 1, limit)) return true; // 注意这个应该从i + 1开始vis[i] = 0;if (sum == 0) return false;                     // 剪枝3,不允许有空桶}}return false;
}int main() {while(scanf("%d",&n) != EOF && n) {int sum = 0;for (int i = 0; i < n; i++) {int b;scanf("%d", &b);a[i] = b;sum += b;}sort(a, a + n, greater<int>()); // 从大到小进行排序, 剪枝1int ans = sum;                   // 如果大于了sum/2就应该是sum,否则就是ifor (int i = a[0]; i <= sum / 2; i++) {memset(vis, 0, sizeof vis);if (sum % i != 0) continue; // 剪枝4, 如果不能整除肯定时不能作为长度的if (check2(0, 0, 0, i)) {ans = i;break;}}printf("%d\n", ans);}return 0;
}

蓝桥杯算法训练sticks相关推荐

  1. 蓝桥杯 算法训练 Sticks

    资源限制 时间限制:1.0s 内存限制:999.4MB Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 113547 ...

  2. java折木棍_蓝桥杯算法训练 Sticks(木棍)问题(JAVA)

    问题描述 乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位.然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度.请你设计一个程序, ...

  3. 蓝桥杯 算法训练 幸运的店家

    蓝桥杯 算法训练 幸运的店家 题目描述 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 炫炫开了一家商店,卖的货只有一个,XXX,XXX卖N元钱.有趣的是,世界上只有面值为3的幂的纸 ...

  4. 蓝桥杯 算法训练 Beaver's Calculator

    蓝桥杯 算法训练 Beaver's Calculator 问题描述 从万能词典来的聪明的海狸已经使我们惊讶了一次.他开发了一种新的计算器,他将此命名为"Beaver's Calculator ...

  5. 蓝桥杯 算法训练 印章

    蓝桥杯 算法训练 印章 共有n种图案的印章,每种图案的出现概率相同.小A买了m张印章,求小A集齐n种印章的概率. 输入输出: 一行两个正整数n和m 一个实数P表示答案,保留4位小数. 样例: 2 3 ...

  6. 蓝桥杯算法训练-24点(Python)

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

  7. 蓝桥杯——算法训练——数字三角形

    蓝桥杯--算法训练--数字三角形 这道题不难,但是比较典型,可以作为动态规划(dp)的入门篇,属于线性dp(LIS,LCS和数字三角形都是此类题型). ------------------------ ...

  8. 蓝桥杯算法训练-强力党逗志芃

    持续更新蓝桥杯算法训练题解,有兴趣可以关注一波呀 题目 逗志芃励志要成为强力党,所以他将身上所以的技能点都洗掉了重新学技能.现在我们可以了解到,每个技能都有一个前提技能,只有学完了前提技能才能学习当前 ...

  9. 蓝桥杯 算法训练 逗志芃的危机

    蓝桥杯 算法训练 逗志芃的危机 题目描述 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 逗志芃又一次面临了危机.逗志芃的妹子是个聪明绝顶的人,相比之下逗志芃就很菜了.现在她妹子要和 ...

最新文章

  1. 微信公众号开发之准备工作
  2. Collection接口详解
  3. Oracle启用、禁用角色
  4. 基于时空相关属性模型的公交到站时间预测算法
  5. datax 模板_datax模板
  6. python初始化函数_当你学会了Python爬虫,网上的图片素材就开始免费了
  7. optparse的模块编译参数使用
  8. matlab 图像的膨胀indilate和腐蚀imerode
  9. excel删除行闪退_excle2017打开就闪退:excel表格打开闪退怎么办
  10. MATLAB基础知识零基础到入门(第一期 基础内容)
  11. php curl jsonrpc,JsonRPC: Lightweight Json-RPC 2.0 client/server in PHP extension
  12. Redis——修改redis配置文件,并使配置生效
  13. 怎么根据分隔符号将Excel数据换行复制
  14. 秦纪二 秦始皇帝二十年(甲戌,公元前227年)——摘要
  15. 设计模式在游戏开发中的应用之观察者模式
  16. 讯飞AIUI智能机器人1
  17. Python按照指定页数分割PDF文件
  18. Python爬虫:老兵不死,用数据纪念2019男篮世界杯
  19. 黑苹果html5,黑苹果配置必备神器 Clover Configurator v5.10.0.0 官方中文原版
  20. jquery获取ip地址

热门文章

  1. ofbiz 新建模块
  2. CSS3 Box Shadow
  3. 拓扑排序详解(超详细+模板)
  4. StructuredStreaming
  5. offsetWidth和width的区别
  6. android模拟器本地浏览器代理,浏览器,Android模拟器或真机如何访问本地电脑的Tomcat...
  7. 电脑显示器vga和dvi
  8. 晶圆WAT(wafer acceptance test)
  9. 技术宅学习Linux系统还是很有前途的
  10. QBarCategoryAxis、QColorAxis、QDateTimeAxis、QLogValueAxis、QValueAxis