SGU 195 New Year Bonus Grant

题意

某厂采用一种奇怪的方式发奖金,给出一个上下级关系树,大BOSS是1号根节点,别的员工都有自己的上司。对于每个员工,它有三种选择,要么接受上级下发的奖金,要么给所有下级发奖金,要么啥都不做(只有傻子才会这样,所以你可以当成没这种选择),大BOSS一定发奖金。只要一个员工选择收奖金,他就得到1000块。

现在要你设计一种方案,使得所有人收到的奖金的总数额最大。

思路

树DP解法

对于每一个节点,都有两种状态:选择收奖金,选择收奖金。

对于选择收奖金的节点的儿子节点,一定不可以选择收奖金。

对于选择发奖金的节点的儿子节点,可以选择收他的奖金,也可以选择发奖金。

这样就可以建立dp数组dp[a][0/1],a是节点对应的编号,0/1表示该节点选择收/发奖金的状态。利用DFS下潜到叶子节点之后,就可以开始树DP了。

状态转移的方程可以参考dfs()方法。

输出路径的话,只要记录下每一次的决策,DP结束之后反查就可以搞定。

贪心解法

引用自JHC23的Blog。

自底而顶遍历,如果自己的上级没有接受奖金(那么就能够把钱给发自己了),而自己也从不增接受奖金则可以获得奖金,同时标记自己和上级。这样下去就可以得到可得到最大奖金。

代码

树DP解法:

 

SGU 126 Boxes

题意

http://www.nocow.cn/index.php/Translate:Sgu/126,翻译版。

思路

我是手写一些找规律,所以我也没办法细讲。

http://www.nocow.cn/index.php/Sgu/126详细题解,说是一个数论题,因为我是找规律所以代码肯定是写不严的,如果你需要严格证明请移步那边。

代码

 

SGU 101 Domino

题意

给你一堆骨牌,每张骨牌正反两面各有一个0~6范围内的数字,你要做的是确定一种骨牌的排列方式和骨牌的正反似的相邻的两个骨牌的面数字一样。

思路

这种链接多个物体,物体之间通过公共部分链接,这种题是可以转换成图论题做的。那么这个题应该怎么转换?
我们建立0~6这7个节点,每张骨牌就可以看作是链接骨牌上两个数的边,我们要做的就是找到一个路径使得我们可以“一笔”走过所有的边,其实这个叫欧拉通路。
关于欧拉通路,欧拉回路的更多细节,可以参看http://haha.school/guanyuoulahuiluheoulalujing/
找出欧拉回路的方法就是DFS,但是和以往不同的是我们把处理工作放在下一层返回之后做。同时本题还需要判断欧拉回路是否存在,如果不存在的话要输出无解。

代码

 

SGU 123 The sum

题意

打出斐波那契数列前41项。

思路

没啥好说的,入门经典题。对于新手来说,容易跪在直接求斐波那契的题的原因一般是没有采用记忆化的方法(存住之前的每一个值),而是每一次都重新推一遍,这样就超时了。要么就是没有注意到int范围弄爆了,或者把longlong弄爆了(这个时候应该是java大法好)。

代码

 

SGU 108 Self-numbers 2

题意

http://www.nocow.cn/index.php/Translate:Sgu/108,翻译版,这里不再多说。

思路

这个题刚到手其实都是会写的,但是一般交上去会发现爆内存,原因就是我们用来判定self number的数组开太大了,要想减少空间复杂度只能从这个数组入手,那么我们真的需要那么大的数组么?显然是不用的,通过本题的数据范围可以发现N最大为7位数,即使7位全是9,我们能够更新到的数组区域长度也仅为63个单位,所以我们把bool标记数组开个63长度就够了,开100那更是没问题,这个技巧就是所谓的“滚动数组”。
滚动数组的操作方法有几点:1.通过求余来确定位置 2.使用完当前位置后,要给它初始化为没有使用过的样子以便以后的元素正常使用。
仅仅使用滚动数组还不足以完成这个题,还要注意输出答案的方式,因为数组在滚动,所以你不可能在完成判定之后再输出结果,而是应该边滚动判定,边记录,最后把记录的输出去。
本题有几个坑点:首先你要把输出的目标索引排个序,否则如果数据是乱序的基本都会跪,其次要注意请求的索引中是有重复的,可能一个索引被请求了多次。

代码

 

SGU 107 987654321 problem

题意

给你n,让你输出n位数中平方后尾数是987654321的数的个数。

思路

一个数,只考虑最后i位,那么这个数平方之后的最后i位和这个数的最后i位平方后的最后i位相同,所以我们只要考虑1~9位数中谁的平方最后9位是987654321就可以了,本地打个表,发现只有8个数符合要求,接下来,对于10位数,我们就有98=72种组合对于11位数就是908=720种组合,这样我们就发现了,超过10位数的话,就在73后面补上n-10个零就行了,这样大数时也搞定了。

代码

 

SGU 104 Little shop of flowers

题意

插花,给你若干花瓶和若干把花,花瓶个数大于等于花的把数,每把花都不一样,要求你让每把花都插进花瓶里面,花瓶不一定每个都要用,但是你必须保证插完之后花的排列顺序和原来给出的一样。然后给了你一个花插进花瓶之后产生的美学价值对照表,要你设计一种方案使得这样插花所达到的美学价值最大。

思路

典型的背包问题,我们设计一个二维dp数组dp[i][j],令i表示当前已经考虑到第几把花,令j表示对于当前这把花我们插入到前j个花瓶,那么我们一把一把花处理,对于每把花枚举其插入每个花瓶的结果,同时要继承上一把花插入到这个花瓶之前的全部状态中最优的那个(因为要保证有序)。最后枚举dp[n][j]的j,找到最佳状态就好了。
接下来要考虑怎么输出最优方案,其实不难想,我们可以给dp数组加上一维或者单开一个pre[i][j]数组,与dp数组平行工作,保存当前状态的前置状态,最后顺着最佳状态不断回溯输出就搞定了。

代码

 

SGU 103 Traffic Lights

题意

http://www.nocow.cn/index.php/Translate:Sgu/103
翻译版,这里不重复劳动了

思路

这个题的可怕之处不是有多难想,而是虽然基本模型很简单就是图上最短路,但是这回有许多许多的限制条件。
正确地计算当前灯的状态是这个题最大的难点,我采用的方法是(其实我写跪了,李大神给我捞上来的):首先把到这个路口已经消耗的时间减去题目给的初始时间,我叫他有效时间,接下来把这个有效时间模上两种颜色的灯持续时间之和,剩下的时间是对灯的状态真正有影响的时间,接下来分别脑内模拟一下站在这个路灯时如果是紫色最后会怎么变,如果是蓝色会怎么变,然后基本就可以写出这个时间和最终颜色的关系了,还可以得到最终这个颜色还能再持续多长时间,这两条非常重要,一定要搞对。
接下来的难点就是计算从当前点移动到下一个点之前等待两点灯的颜色同步的时间,算这个就要依赖于上面的两个值:当前颜色和当前颜色还剩多长时间,假设我们要从A点移动到B,已经走了tim时间,那么我们就要分别计算A点和B点在tim时的这两个数据,然后如果AB在tim时颜色正好相等,那么无需等待直接通行,所以等待时间为0,如果颜色不同呢?只要看A和B哪个剩余的时间短,这个就是等待时间了。要是剩余的时间又一样?那就要脑内模拟一下了,然后发现我们可以再比较A的下一颜色和B的下一颜色谁的持续时间短,等待时间就是剩余时间+最短的持续时间。如果下一个颜色还一样,那就比较下下个颜色。要是还一样?对不起,hehe了,走别的吧~(所以说这个题很sxbk)
接下来是最段路部分,我们把权值设定为走到这个点要花多少时间,从当前点走到下一个点时,下一个点的可能值就是(当前点已用时间+等待两个点的灯同步的时间+路上消耗的时间),以此为基准进行松弛操作。

接下来上代码

 

SGU 102 Coprimes

这个题是欧拉函数:http://baike.baidu.com/view/107769.htm,正好就是这货的定义,说实话我都不知道欧拉函数是啥,打表又没意思了。。。

简单的说就是这个数挨个乘上(n-1)/n,n是不同的质因数。

贴一个求欧拉函数更好的姿势:

降幂公式 a^b %c= a^(b%phi(c)+phi(c)) %c (b>=phi(c))

这个是意外收获,可以用到欧拉函数的地方。

SGU 105 Div3

如果每一位加合等于3的话,这个数也可以被3整除。

然后打个表找下循环节发现是XOOXOOXOO这样的,直接简单判定一下实现就好了。

Scroll to top