A. 牛牛分蛋糕

题目描述

牛牛今天家里要来客人,所以牛牛今天特意做了他最拿手的两种蛋糕,但是他是一个有洁癖的人,所以他在分蛋糕时,有如下几个原则:

他不希望一个盘子里出现两种蛋糕

他希望每个盘子中都有蛋糕

他想让装有最少蛋糕数量的盘子中装有的蛋糕数量尽可能多

备注:

n, a, b(1 ≤ a, b ≤ 10^5, 2 ≤ n ≤ a + b)

第一个参数代表盘子的数量

第二个参数代表第一种蛋糕的数量

第三个参数代表第二种蛋糕的数量。

程序应返回:在所有分法中,蛋糕数量最少的盘子中分到最多的蛋糕数量。

示例1

输入

5, 2, 3

输出

1

说明

只有一种方法把蛋糕分配到盘子里,即所有的盘子上都有一个蛋糕。

示例2

输入

4, 7, 10

输出

3

说明

第一个盘子中装有第一种蛋糕三个,第二个盘子中装有第一种蛋糕四个,第三个、第四个盘子中各装有第二种蛋糕五个。

解法一:暴力搜盘子

思路分析

要想装最少蛋糕数量的盘子中装的蛋糕最多,必定是均匀分配蛋糕。因此可以搜索所有的盘子分配方案,看哪种情况下均匀分配到的蛋糕最多。

时间复杂度:$O(n)$。总共有 $n - 1$ 种盘子分配方案。

空间复杂度:$O(1)$。

代码实现

public int solve (int n, int a, int b) {

int res = 0;

for(int i = 1; i < n; i++) {

int min = Math.min(a / i, b / (n - i));

res = Math.max(res, min);

}

return res;

}

解法二:二分搜蛋糕

思路分析

每个盘子都分配 $c$ 块蛋糕,若 $a / c + b / c \ge n$ 说明这样分配能使 $n$ 个盘子中都有蛋糕。二分搜索寻找最大的 $c$ 即可。

时间复杂度:$O(log(min(a,b)))$。

空间复杂度:$O(1)$

代码实现

public int solve (int n, int a, int b) {

int l = 1, r = Math.min(a, b);

while(l < r){

int mid = (l + r + 1) >> 1;

if(a / mid + b / mid < n) r = mid - 1;

else l = mid;

}

return l;

}

B. 牛牛凑数字

题目描述

牛牛今天逛商店,看到商店里摆着一些很漂亮的数字,牛牛非常喜欢,想买一些数字带回家。

数字一共有九种类型,分别是 1 - 9 这九个数字,每个数字的价钱都不一样,而且每个数字的货源都非常充足。

牛牛是个完美主义者,他希望用自己的能够承受的价格,从这些数字里面购买,并且凑到最大的数字带回家。

备注:

第一个参数为一个整数 n(0 ≤ n ≤ 10^6),代表牛牛所能承受的价格。

第二个参数为 1 - 9 这九个数字的价格数组,a1, a2, ……, a9(1 ≤ ai ≤ 10^5)。

程序应返回:一个数字,代表牛牛能凑到的最大的数字。当然,如果牛牛一个数字都买不起,返回 "-1" 即可。

注意,由于数字可能会很大,所以程序中需要处理成 string 类型进行返回。

示例1

输入

5,[5,4,3,2,1,2,3,4,5]

输出

"55555"

说明

第 5 个数字只需要花费 1,所以买 5 个第 5 个数字可以凑到最大值 55555。

示例2

输入

2,[9,11,1,12,5,8,9,10,6]

输出

"33"

说明

购买 2 个第 3 个数字,可以凑到最大值为 33。

解法:贪心

思路分析

要想数字最大,首先得数字的数量最多。其次,在相同数量的数字时,应尽可能买最大的数字。

如果每一个都买花费最少的数字 $a$,那么数字的数量 $cnt$ 必定是最多的。

找到这个最多的数量后,从大到小搜寻数字,若不减少数量的情况下能买到更大的数字,则用它替换掉 $a$。

时间复杂度:$O(\frac n {min(a_i)})$。最多买 $\frac n {min(a_i)}$ 个数字,因此最多搜寻这么多次。

空间复杂度:$O(1)$。

代码实现

public String solve (int n, int[] a) {

StringBuilder res = new StringBuilder();

int min = Integer.MAX_VALUE;

int minNum = 0;

for(int i = 0; i < 9; i++ ) {

if(a[i] <= min) {

min = a[i];

minNum = i + 1;

}

}

if(n < min) return "-1";

boolean incre = true;

while(incre && n > min) {

incre = false;

for(int i = 8; i >= minNum; i--) {

if(n >= a[i] && ((n - a[i]) / min == n / min - 1)) {

res.append(i + 1);

n -= a[i];

incre = true;

break;

}

}

}

for(int i = 1; i <= n / min; i++) res.append(minNum);

return res.toString();

}

另一种写法(时间复杂度没变,只是降低了代码量)

public String solve (int n, int[] a) {

StringBuilder res = new StringBuilder();

int minCost = Integer.MAX_VALUE;

for(int i = 0; i < 9; i++ ) minCost = Math.min(minCost, a[i]);

if(n < minCost) return "-1";

int cnt = n / minCost;

for(int i = 8; i >= 0 && res.length() < cnt; i--){

while(n - a[i] >= minCost * (cnt - res.length() -1)){

res.append(i + 1);

n -= a[i];

if(res.length() == cnt) break;

}

}

return res.toString();

}

C. 牛妹的野菜

题目描述

书接上回,牛妹组织春游,有一个有趣的项目是挖番薯。聪明的牛妹拿到了一个标明了番薯洞的地图,每个番薯洞中有一定数量的番薯。同时,我们知道番薯洞的连接路径,并规定路径是单向且小序号指向大序号,也无环。可以从任意一处开始挖,然后沿着连接往下挖(仅能选择一条路径),当无连接时,结束。

设计一种挖番薯的方案,使得可以挖到更多的番薯。

输出路径。

备注:

总番薯数量不超过1000000,番薯洞数量不超过250.

示例1

输入

[5,10,20,5,4,5],[[1,2],[1,4],[2,4],[3,4],[4,5],[4,6],[5,6]]

输出

"3-4-5-6"

说明

很明显 先去第三点拿20个番薯,再去第四个点拿5个,再去第五个点拿4个,再去第六个点拿5个。这个方案最优

解法: 回溯

思路分析

(内心 os: 作为成年人,所有番薯我全要。一条路径上的番薯只够牛妹一个人吃!)

当我们处于洞口 $a$ 时,如果我们知道了每一个洞口 $b (b \in next(a))$ 的最优方案,那么可以直接比较集合 $next(a)$ 的各个方案,选择其中最优的作为下一个洞口。

依照这个思路,我们只要从路径的底部往头搜寻,就可以一次遍历得到所有洞口的最优方案。那么如何找到路径的底部呢?答案就是利用回溯。从入口递归的往下搜寻洞口,然后回溯中返回下一个洞口的最优方案。

时间复杂度:$O(n)$。每个洞口最多搜寻一次

空间复杂度:$O(n^2)$。对于 $n$ 个洞口,需要记录它们的下一个洞口。

代码实现

List[] next; // 从 i 出发的下一个洞口

String[] path; // 从 i 出发的最优方案路径

int[] potatoMaxNum; //从 i 出发可以挖到番薯的最大数量

int[] potatoNum;

public String digSum (int[] potatoNum, int[][] connectRoad) {

int n = potatoNum.length;

next = new List[n + 1];

path = new String[n + 1];

potatoMaxNum = new int[n + 1];

this.potatoNum = potatoNum;

for(int i = 1; i <= n; i++) next[i] = new ArrayList(250);

for(int[] path: connectRoad){

next[path[0]].add(path[1]);

}

String res = "";

int maxNum = 0;

for(int i = 1; i <= n; i++) {//遍历 n 个洞口,看看哪个洞口出发得到的番薯最多

dfs(i);

if(potatoMaxNum[i] > maxNum) {

maxNum = potatoMaxNum[i];

res = path[i];

}

}

return res;

}

public int dfs(int d){//返回洞口 d 出发得到的最大番薯数量

if(potatoMaxNum[d] != 0) return potatoMaxNum[d];

if(next[d].isEmpty()) {//最后一个洞口了

path[d] = "" + d;

return potatoMaxNum[d] = potatoNum[d - 1];

}

int maxd = d;

for(Integer nextd: next[d]) {//看看下一步去哪个洞口得到的番薯最多

int num = dfs(nextd);

if(num > potatoMaxNum[maxd]) maxd = nextd;

}

potatoMaxNum[d] = potatoNum[d - 1] + potatoMaxNum[maxd];

path[d] = d + "-" + path[maxd];

return potatoMaxNum[d];

}

写在最后

大家好,我是往西汪,一位坚持原创的新人博主。

如果本文对你有帮助,请动动你的小手指点个赞

凑数算法 c语言,算法题解 - 牛客编程巅峰赛S1第4场 - 黄金钻石组相关推荐

  1. 算法题解 - 牛客编程巅峰赛S1第3场 - 黄金钻石组

    A. 找卧底 题目描述 牛牛今天和大家玩了一个新游戏,除了牛牛以外还有 n 个人参加游戏,现在这 n 个人中的每个人从 [1, n] 中选择一个数字,保证选出的数字均不重复.牛牛作为第 n + 1 个 ...

  2. 牛客编程巅峰赛S1第6场 - 黄金钻石王者(总结)

    牛客编程巅峰赛S1第6场 - 黄金&钻石&王者(总结) A:牛牛爱奇数 题意 有一个由n个元素组成的数组,牛牛想要将所有的数都变成奇数(即:将所有的偶数都变成奇数),但是他的操作是:一 ...

  3. 牛客编程巅峰赛S1第7场 - 黄金钻石A-B-C

    比赛链接:牛客编程巅峰赛S1第7场 - 黄金&钻石 文章目录 A.牛牛打怪兽 DFS B.牛牛的冰激凌 贪心 C.数列求值 矩阵快速幂 A.牛牛打怪兽 DFS 题意 身为屯里第一剑士的牛牛来到 ...

  4. 牛客编程巅峰赛S1第6场 - 黄金钻石王者题解

    牛牛爱奇数 链接:https://ac.nowcoder.com/acm/contest/6629/A 来源:牛客网 题目描述 在牛牛面前放着n个数,这些数字既有奇数也有偶数,只不过牛牛对奇数情有独钟 ...

  5. 牛客编程巅峰赛S1第3场 - 黄金钻石 A.简单题 B.dfs C.并查集

    链接:https://ac.nowcoder.com/acm/contest/6383/A 来源:牛客网 找卧底 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语 ...

  6. 牛客编程巅峰赛S1第7场 - 黄金钻石 A.dfs B.dpC.快速幂

    链接:https://ac.nowcoder.com/acm/contest/6631/A 来源:牛客网 题目描述 题意 身为屯里第一剑士的牛牛来到训练场里闯关,由于过于勤奋,牛牛的宝剑的耐久度降到了 ...

  7. 牛客编程巅峰赛S1第2场 - 黄金钻石 1.规律 2.bfs

    链接:https://ac.nowcoder.com/acm/contest/6357/A 来源:牛客网 题目描述 牛牛重新定义了斐波那契数列,牛牛定义f(n) = f(n-1)+f(n+1); f( ...

  8. 牛客编程巅峰赛S1第6场 - 黄金钻石王者 C.dijkstra

    链接:https://ac.nowcoder.com/acm/contest/6629/C 来源:牛客网 题目描述 牛牛和牛妹在进行一场星球模拟游戏,游戏规则如下: 游戏地图内共有n个星球,共有m条隧 ...

  9. 牛客编程巅峰赛S1第2场 - 青铜白银

    A.牛牛扔牌 链接:https://ac.nowcoder.com/acm/contest/6219/A 来源:牛客网 题目描述 牛牛现在有n张扑克牌,每张扑克牌都有点数和花色两部分组成.点数为'1' ...

  10. 牛客编程巅峰赛S2第5场 - 钻石王者 C.Tree III

    牛客编程巅峰赛S2第5场 - 钻石&王者 C.Tree III 题目链接 题目描述 给出一棵有n个节点的节点标号为1~n的有根树(根为第一个节点,并给出从第2个节点到第n个节点的父结点),请你 ...

最新文章

  1. c#索引器介绍|C#索引器写法|c#索引器例子
  2. linux服务器ftp上传文件为空,Linux 服务器 ftp上传文件出现的问题
  3. 第3周实践项目4 -顺序表的应用 删除顺序表中元素为x的值
  4. 如何在window上把你的项目提交到github
  5. C++的三种访问权限的继承
  6. linux合并两个文件 去重复,c - 在Linux中使用C,通过系统调用将两个文本文件合并为一个新文件(来回换行) - 堆栈内存溢出...
  7. centos httpd服务做yum本地源,以及安装Mysql
  8. JavaScript中十个一步拷贝数组的方法
  9. win10计算机添加右键菜单,win10系统如何对鼠标右键菜单进行手动管理和添加
  10. 爬虫python能做什么-Python 爬虫学到什么样就可以找工作了?
  11. Inno Setup for Windows service
  12. android系统级浮层,android 新手引导浮层的实现
  13. html视频播放卡顿,网页看视频卡怎么解决
  14. java lpad oracle_Oracle中Lpad函数和Rpad函数的用法
  15. CS_2022_01
  16. java jisuan da xie zi mu ge shu_java获取中文拼音
  17. 各大公司Java面试题超详细总结
  18. Python爬虫《自动化学报》数据爬取与数据分析
  19. 王烁老师 - 问得太少你吃亏
  20. Axure RP Pro 8.1.0.3377中文破解正式版(附注册码)

热门文章

  1. 梯度消失和梯度爆炸原因及其解决方案
  2. win2003 序列号 windows2003 sp2可用序列号大全(准版与企业版)
  3. 浏览器架构的误区和瘦客户端应用
  4. 怎么缩小gif动图的体积?三步快速压缩gif体积
  5. 计算机拨号连接无法建立连接,电信拨号上网连接不上的解决方法
  6. 程序员薪资:2022年腾讯校招薪资接近40W?我惊呆了
  7. 关于安装软件时x86 ,x64,x86_64,ARM 64, ARM 32 的选择
  8. 186.MultiAutoCompleteTextView
  9. 算法面试和实习经验分享
  10. 浅谈制药企业安全供电系统的设计与应用