问题描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤64。 第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
输出
仅一行,表示要求的原始木棍的最小可能长度。
思路
依然还是爆搜。
代码
1 |
|
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤64。 第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
仅一行,表示要求的原始木棍的最小可能长度。
依然还是爆搜。
1 | #include <bits/stdc++.h> |
需要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体。设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱。当i < M时,要求Ri > Ri+1且Hi > Hi+1。 我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。 令Q = Sπ 。
请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小(除Q外,以上所有数据皆为正整数)。
有两行,第一行为N(N <= 10000),表示待制作的蛋糕的体积为Nπ;第二行为M(M <= 20),表示蛋糕的层数为M。
仅一行,是一个正整数S(若无解则S = 0)。
一开始什么思路都没有,然后就手玩了一下样例。样例玩了很久才出来,然后发现玩样例的过程就是个搜索的过程。
所以这道题就可以用爆搜去做,爆搜不难写,但剪枝就没那么容易。首先可以预处理出剩下i层最小的蛋糕体积,储存为minv[i]。如果搜索剩下了i层,但剩余的体积小于minv[i]时,就可以剪去这枝。然后,如果剩余体积/最大半径* 2(即为最大侧面积)大于等于已知的最小侧面积时,也可以剪去这枝。
加上这两个以后,就可以从原来TLE8个点变为0ms了。
1 | #include <cstdio> |
给你在平面直角坐标中的n个点,以及点的高度。两个点的高度之差代表该边的成本,两点的欧几里得距离代表该边的长度(这个可以看成一个完全图)。你需要找出一个成本之和/长度之和最小的生成树。
有多组数据,每组数据第一行包含n(以n=0结束输入)。 接下来n行,每行有包含3个数,表示一个点的横坐标,纵坐标和高度。
输出长度之和/成本之和的最小值,保留小数点后3位。
看到求其中
式子的最值,这就是01分数规划问题,这道题就属于01分数规划中比较水的。
首先二分答案,然后将图上所有边权改为成本-(答案* 该边长度)。然后找一棵最小生成树,若它的边权之和小于0则r=mid,否则l=mid。直到答案符合精度要求。
其实还有一种迭代的方法,比二分优很多。还是同样的思路,只是代码作了一点小的该动。
二分的代码:
1 | #include <cstdio> |
迭代的代码:
1 | #include <cstdio> |
给你一张含有n个点m条边的无向图,求出一个最小生成树,满足1号节点的度数不超过给定整数s。
第一行给出一个整数m,表示有m条边。 接下来m行,每一行有两个字符串表示节点以及它们之间的距离。 最后一行给出整数s。
输出一行:Total miles driven: xxx xxx 表示最小生成树的边权之和。
其实这个东西说的高大上一点是度限制生成树,但是本身并不难理解。
首先是用常规的Kruskal建一个最小生成树,然后把这棵生成树去掉1号节点。统计有多少个联通块,联通块个数记为t,然后从1号点和每一个联通块连一条最短的边。这样一来我们就得出了一个一号节点度数为t的最小生成树。
如果t大于s,则不存在题目要求的树(当然本题不包含这种情况)。 如果t等于s,则不需要其他操作,直接输出边权之和就好了。 如果t小于s,则我们需要调整这棵树,使它的边权之和更小。
调整这棵树,我们可以改动s-t条边(或者更少)。考虑从1号节点出发的每一条边,设它的到达节点x,边权为z。如果该边不在生成树中,则我们可以找出从1号点到x号点树上路径的最长边,设该边边权为y(这个我们可以通过一次dfs预处理出来)。那么我们可以找出一个节点x,使它的z-y最大。z-y就是这次调整能够减少的最大边权(把最长边去掉,加上从1出发到达x的这条边)。重复这次操作s-t次,就可以得到题目要求的最小生成树。
1 | #include <cstdio> |
大意就是给你一个无向图,求出它的最小环。 并输出最小环上的点。(会有SPJ)
第一行n(n<=100), m(m<=10000)。表示有n个点,m条边。 接下来m行,每一行描述一条边。
输出最小环上的所有节点
求最小环是用Floyd的方法。
我们按顺序枚举所有点,再枚举与该点相邻的点对。枚举点对时,我们可以不需要考虑编号比该点大的点,因为编号比它大的点在后面会被枚举到,会包含这种情况。环的长度就是该点到点对的距离与点对之间的距离之和。
接下来考虑输出环上的点。记录路径感觉很难,于是膜了一下书上的做法。每进行一次松弛操作时就记录一下。环上的点就是点对之间的最短路径上的点和该点对。可以递归下去找最短路径上的点,有点像记录DP方案。(似乎有点难讲清楚,代码还是比较好懂的)。
1 | #include <cstdio> |