随笔分类 - 贪心
摘要:题意:比赛的时候想了各种的贪心方案,最后还是没有把这题搞出来......废话不多说,题目给定了一条条给定了顺序的路径,这些路径是后面要一一走过的,每条路径有一个长度,单位长度消耗汽油的量以及该条公路上加油站的汽油单价。告诉你路径条数N,油箱容积K,问如何安排加油是的行走完所有路径的花费最少。解法:该题有一个很巧妙的解法就是每到一个油站都加满油箱,队列里面保留了走过前面路径后保留的最便宜的油,每次从队列中取出最便宜的油行进这一段路程。在维持一个汽油价格单调递增时,具体过程如下:1.当队尾不为空时,每次从队尾向前遍历,如果元素单价高于当前路线加油站的汽油单价,替换之,知道遇到价格比其低的汽油或者队
阅读全文
摘要:这题有两种解法, 一种是通过动态规划弥补一个不太成熟的贪心思路, 使得最后的结果正确. 另一种方法是构造一个更好的贪心策略.动态规划依托的结论: 每次给齐王最强的马匹配一匹田忌的马, 那么这匹马不是田忌最强的马就是最弱的马, 这一个不完善的贪心策略. 所以动态规划佐之.#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;/*解法:开设状态dp[i][j]表示田忌出了
阅读全文
摘要:这题题意在代码中有解释, 求的最优值初看不太好理解. 求的是给定一个决策下的找到房子的最优期望值. 那么这题其实要做的就是一件事那就是给所有的分叉口的选择拍一个次序出来.根据这个次序我们就能够给出这只蜗牛在碰到有所情况下的唯一的一条爬行路线. 题目就是当我们安排好这样的这个次序后, 假设房子在各个叶子节点时, 需要走的路径总长最小. 这里的每一棵子树, 在枚举的过程中总是充当着不同的角色, 当枚举到的房子在自己的子树中时, 其要考虑能够安排最快的路径让蜗牛找到. 当没有在自己的子树时又不想让其放在前面让蜗牛白忙活一场. 所以综合一看, 貌似是一个很复杂的问题. 但是这题就是在如何安排子节点访问
阅读全文
摘要:题意:有一个国王要把他的领土分给两个儿子,国王的领土是一棵树,N个结点,N-1条边把这些结点连起来,现在大小儿子要选择一个点作为他的首都,那么除首都分别是这两个儿子之外,其他的城市(结点)根据离谁近就归谁所有,如果一样远的话就归大儿子所有,现在假设两个人都采取最优策略,且大儿子先选,问大儿子最多能够得到多少城市?解法:如果大儿子选择了一个点P,那么这个小儿子选择的点一定在P点的某个子树(M)当中,且P的其他子树一定归大儿子所有,对于子树M,小儿子的最优策略显然是选择和P相邻的哪一个点,否则将损失更多的城市。那么最后的解法就是大儿子选择一定P,改点满足P的所有的子树中拥有最大结点数的子树最小。这
阅读全文
摘要:题意:给定一张图,现在对这张图进行染色,且相邻的两个点的颜色不能够相同,问最少要用多少种颜色?思路:有一下贪心思路,对于没一个节点,我们对其周围的结点进行遍历,对有颜色的邻节点的颜色进行统计,选取一种编号最靠前且不与周边颜色冲突的颜色对改点进行涂色。由 于我们的涂色都是按编号从小到大因此该策略下能够产生最小的颜色集合。可以简单的证明下:假设现有N个点,对部分点已经进行了涂色,且满足条件,现在问题就是我们 的算法在要添加一种新颜色的时候还在用以前的颜色,导致后面出现了更多的颜色开销(违背贪心规则,如果确实这样的话,此题则变为动态规划求解),但是我们得出的推 论是,如果一个点应该被涂...
阅读全文
摘要:题意:给定一棵树(不一定是二叉树),现在问最多能够删除多少条边使得分开的结点满足分开子树的结点数都是偶数。思路:首先用邻接表建立起一棵树,然后我们得出以下的结论:对于任意结点而言,如果该节点能够找出和与之相连的部分子树构成偶数个点并且这偶数个点不能再分解出偶数个结点的分支出来,那么这个点与其他相连的子树(没有加入前面的集合中)的边全部断掉。之所以可以断掉这些边是因为一个我们去掉的点集都是不能够再进行分割的集合,而且又达到了偶数个点,那么这偶数个点对于其他集合肯定也是没有帮助的,因为%2之后的贡献率为0。代码如下:#include <iostream>#include <cst
阅读全文
摘要:该题建立一个一维的坐标,给定N,M分别表示有N个接收器,M个房子(坐标分别是1,2,3...M),每个接收器能够接受来自左边和右边的一个通话,下面跟着N行,分别表示每个接收器的属性,两个参数,首先是这个接收器的位置,给定为a的话,那么其位置就是位于a和a+1之间,第二个参数就是来自左右有多少个通话。我们定义一个贪心规则即是:只考虑到左边发射出去的线,对于每个接收器(a, b)就把问题转化为在坐标小于等于a的地方有b条线段存在,如果左边剩下的线段条数没有b条的话,那么增加至b条,否则则属于线段过多,应该马上连接x-b条线段,这样多出来的线段就不会穿越这个位置的接收器了。代码如下:#include
阅读全文
摘要:这题用匈牙利算法是无论如何也过不了的,边太多了。利用简单的贪心规则,我们每次选取最优的匹配方案来进行匹配,在划分上我们采用工资要求为负值的去寻找工资要求为正值的人。对于一个要求工资比他低的男人来说,其实就是优先最有钱的男人,因为能与之匹配的女生是最多的,在选取女生的时候,就选择满足要求下工资最高的女生,因为这种女生最难满足要求,这一对配对对后面的匹配来说是最优的。女生同理。代码如下:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#define MA
阅读全文
摘要:这题用也算是贪心吧,不过这里有一点数学思想。对于要取掉K位的N位数,那么我们留下来的就是N-K位,我们不妨设 T = N - K; 那么我们选择的第一位数的后面就一定要有T-1个数让我们来选,因此第一个数的选择范围就是[1, N-T+1],当我们选取了第一个数后(假设位置为P),我们第二个数的选择范围就是 [P+1, N-T-2]了,一次类推。由于我们要取的是最大的数,所以我们每次都选取区间内的最大值,用线段树来作优化就可以了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include
阅读全文
摘要:对于一个串,我们可以这样考虑,首先我们从串的最后面开始向前遍历。对于一个串是 "XXXXAA",那么对于后面这两个A,我们是不用做任何考虑的,我们甚至可以直接认为这个串没有后面这两位。对于一个串是 "XXXXBB",那么我们是一定要选择反转的,因为单次操作的话将这两个(或者多个)B变成A需要两次操作,而我们通过翻转整个串,再翻转前N-2个串同样可以达到这个效果。但是我们翻转整个串可能为前面的字符串改变作了贡献。对于一个串是 "XXXXAB",那么我们是一定进行单个字符替换的。我们可以这样考虑,如果我们通过一次翻转操作来改变最后面的这一
阅读全文
摘要:这题题意是别人告诉的,现在这里表示感谢了。题目就是说给定一个盈利和一个亏损值,(一个月只可能盈利或者亏损)一年12个月,任意连续5个月的和值必须亏损。求十二个月的最大盈利是多少?解题思路:先确定前五个月的安排情况,把亏损的尽量安排靠后,然后再从2月到8月为起点进行暴力,每次能够新确定一个月的盈亏情况(根据5月之和小于零)。最后再确认12个月是否盈利。代码如下:#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>using namespace std;in
阅读全文
摘要:以每个点算出左右覆盖的雷达所在x轴范围,然后贪心计算出所需圆的个数。当后一个点的圆心在x轴的左坐标在前一个点的右坐标的右坐标之前,则这个点就会被覆盖。代码如下:(C++能过,G++ runtime error)#include <cstring>#include <cstdlib>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;int N, R;struct Node{ double l, r; bool operator < (N
阅读全文
摘要:这题真的要设身处地为该题想一想才能感受到这一贪心规则,题目是要求用所给定的硬币,根据面值和数目求出能每天给出不少与C元的次数。对于面值大于C的硬币,没有办法,我们只能够一次性给他们,但在这上面我们不许要再添加其他的硬币。而对于比C小的硬币,我们应该让这些分散的硬币集合到一起,使得其组合值在大于或等于C的指导思想下无限接近于C,于是对于这些硬币我就不停的塞硬币,这一次不能够超过C的值,当然我们优先会塞面值大的,因为这些硬币是不可分割的,小的硬币更具灵活性。在上一步之后,(如果没有塞到C的话)我们在考虑找一些硬币使得其值略微超过C,于是第二次我们从小的开始塞,而且一定是只塞一枚就会超过C。代码如下
阅读全文
摘要:http://acm.hdu.edu.cn/showproblem.php?pid=1789题义是给定一个作业序列,求如何分配使得得到的分数最多。设 dp[i][j] 代表截止到第i个作业,第j天所能够完成的最多分数。dp方程为:if (1<= j <= e[i].time) dp[i][j] = max(dp[i-1][j], d[i-1][j-1]+e[i].score);if (e[i].time+1 <= j <= Last) dp[i][j] = max(dp[i-1][j], dp[i][j-1]);代码如下:#include <cstdlib>
阅读全文
摘要:一个很朴素的问题,但是貌似以前没有接触到过,给定一个长度的棍子,现在要得到三种规格的棍子,每种若干条,问最少需要多少条长棍来分成三种棍子。 一开始用模拟,结果超时了,后面想想思路也是错的。这题应该是这样去考虑,现在想象我们是一个木匠师傅,现在要为客户来解决这个问题,当我拿到一根长为75的木棍时,我肯定要物尽其极,最大利用率的截断方式是 75 = 20 + 20 + 32 次之 为 75 = 20 + 20 + 28 , 再者为 75 = 20 + 20 + 20, 这时截成三段,当然还可以截成两段,这时组合方式就没有关系了,因为前面已经算完了所有组成三段的可能,也就不许要考虑剩余的多少问...
阅读全文
摘要:题目:给定一个数字串0 - N-1,每次可以移动首位数字到末尾,求最少的逆序对的组合方式。先求出原序列的逆序对,再用数学公式算出最佳值。 假设有 10 个数,依题义为 0 - 9,那么首位为4的话,从首位移动到末尾产生新的逆序对为0 - 9中大于4的数字减去少于4的数。 代码如下:#include <cstdio>#include <cstring>#include <cstdlib>using namespace std;int N, num[5005];void getint( int &t ){ char c; while( c= getcha
阅读全文
摘要:该题给定一个容器的体积,以及N个物品,每个物品有其要求的最少空间以及实际所占的空间 。 要我们判断是否可以把所有的物品全部放在里面,当然如果能够放进去也是需要一定的顺序的。最好的放置方法就是每次将物品中所占空间与实际空间差值最大的首先放进去。 现在我们来证明这个差值排序的正确性: 先申明几个变量的符号: CUR_MAX_V 当前的最大体积 ; CUR_NULL_V 当前的空余的体积 ;T_MAX_V 当前物品的所需的体积 ; T_REAL_V 当前物品的实际体积现在假设有一个无限大的空间,保证能够将所有的物品放入,考虑到当前的体积与即将放入的物品有如下关系: ( CUR_MAX_V ) ( .
阅读全文
摘要:I NEED A OFFER!Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5280Accepted Submission(s): 1799Problem DescriptionSpeakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了。要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的。Speakless没有多少钱,总共只攒了n万美元。他将在m个学校中选择若干的(当然要在他的
阅读全文