NHOI2019总结

T1~T3略过

T4 货币系统

首先考虑没有新面值的情况,可以知道所用的最小面值可以用下面的伪代码求出:

for i = 15 downto 1
    ans += money / c[i]
    money %= c[i]

这是一个贪心,因为原本的面值都是一个数字加几位0,所以money的每一位都分开计算,然后加起来就可以了,然后每一位都有1,2,5三种选择,那么每个数字对应的纸币数如下:

这里有一个规律,就是第二列的数字是第一列数字被1,2,5做整除和取模得到的。

接下来考虑新面值,我们因为新面值的面值没有原来面值的特殊性,所以我们采取暴力,枚举使用张数,最多使用50000张,然后剩下的用上面的程序求出使用个数,

T5 蜈蚣

题目这可以转变为:首先浪费掉可以浪费的袜子,然后满足每一条蜈蚣,然后每条蜈蚣分别浪费掉一些。

首先,对于一种颜色 i i i,如果 a i < F a_i<F ai<F,那么这种颜色的袜子要全部浪费掉。而如果 a i ≥ F a_i\ge F aiF,那么要浪费掉 F − 1 F-1 F1只袜子,显然剩下 a i − F + 1 a_i-F+1 aiF+1只。(接下来每次出现 a i a_i ai都表示剩下的袜子数,而不是题面的意思)

现在我们逐只蜈蚣进行分配,首先我们要在剩下数量最多的袜子中拿到一只,这样就可以满足一只蜈蚣,然后在剩下最多的颜色 p p p中浪费掉 min ⁡ { a p , F − 1 } \min\{a_p, F-1\} min{ap,F1},如果在浪费之前 a p a_p ap已经为 0 0 0,这样表明答案是无解,否则接着满足下一只蜈蚣。

T6 珠宝

本题使用状态压缩dp完成,不过在思考方程之前,我们要做一些有意思的思考。

首先看看这个样例:

其中小方块是同一种颜色,我们要将它们合并。用子问题的方式思考合并策略,我们可以发现有两种:

  1. 首先将第二个开始的所有珍珠放好,然后将第一个珍珠放入已经排好的序列中。

  2. 选取一段前缀保持不动,它的首尾都是这种颜色,然后将这段前缀中所有其他颜色的珍珠拿到后面合并,它们的处理方法和1.类似,都是将后面的其他颜色珍珠放好,接着将它们分别放好,然后将剩下的这种颜色的珍珠放入这段前缀之间。

这样相当于将原来的操作分为两部分:将珍珠拿出,放入一个假想的中转站,然后将步数 + 1 +1 +1;将这个珍珠从中转站中拿出,放入想放入到位置,步数不变。

现在我们来定义状态: f ( i , S ) f(i,S) f(i,S)表示原序列前 i i i个珍珠中选取颜色包含在集合 S S S中的所有珍珠,将他们排好。然后还有两个辅助的函数 s 1 c ( i , j ) s1_c(i,j) s1c(i,j),表示原序列前 i   t o   j i~to~j i to j中珍珠中颜色为 c c c的个数。 s 2 S ( i , j ) s2_S(i,j) s2S(i,j)表示原序列中前 i   t o   j i~to~j i to j个珍珠中颜色包含在集合 S S S中的个数。

显然,如果 i > n i>n i>n或者 S = N U L L S=\mathrm{NULL} S=NULL的时候 f ( i , S ) = 0 f(i,S)=0 f(i,S)=0.

对于剩下的情况,我们可以写出方程:

f ( i , S ) = { f ( i + 1 , S ) i f    i ∉ S min ⁡ { f ( i + 1 , S ) + 1 min ⁡ i ≤ p , c p = c i { f ( p + 1 , S − c i ) + s 1 c p ( p + 1 , n ) + s 2 S − c i ( i , p ) } i f    i ∈ S f(i,S)=\begin{cases} f(i+1,S)& if~~i\notin S\\ \min\begin{cases} f(i+1,S)+1\\ \min\limits_{i\leq p,c_p=c_i}\{f(p+1,S-{c_i})+s1_{c_p}(p+1,n)+s2_{S-{c_i}}(i,p)\} \end{cases}& if~~i\in S \end{cases} f(i,S)=f(i+1,S)minf(i+1,S)+1ip,cp=cimin{f(p+1,Sci)+s1cp(p+1,n)+s2Sci(i,p)}if  i/Sif  iS

有一点点长,但是理解起来其实困难不大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值