首页 > 代码库 > NOIP2010解题报告
NOIP2010解题报告
今天状态不错。。1个小时AC了前3题,第四题第一次也拿到了80%的分数,后来换了算法才拿到全部分数。。
第一题:
小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。
这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。
假设内存中有M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。
解题过程:
1.本来以为会是恶心的字符串题,结果竟然是数字代替单词。。果然第一题一般都是水题。。
2.类似循环队列,开一个队列,查找更新即可。
第二题:
小明过生日的时候,爸爸送给他一副乌龟棋当作礼物。
乌龟棋的棋盘是一行N 个格子,每个格子上一个分数(非负整数)。棋盘第1 格是唯一的起点,第N 格是终点,游戏要求玩家控制一个乌龟棋子从起点出发走到终点。
乌龟棋中M 张爬行卡片,分成4 种不同的类型(M 张卡片中不一定包含所有4 种类型的卡片,见样例),每种类型的卡片上分别标有1、2、3、4 四个数字之一,表示使用这种卡片后,乌龟棋子将向前爬行相应的格子数。游戏中,玩家每次需要从所有的爬行卡片中选择一张之前没有使用过的爬行卡片,控制乌龟棋子前进相应的格子数,每张卡片只能使用一次。游戏中,乌龟棋子自动获得起点格子的分数,并且在后续的爬行中每到达一个格子,就得到该格子相应的分数。玩家最终游戏得分就是乌龟棋子从起点到终点过程中到过的所有格子的分数总和。
很明显,用不同的爬行卡片使用顺序会使得最终游戏的得分不同,小明想要找到一种卡片使用顺序使得最终游戏得分最多。
现在,告诉你棋盘上每个格子的分数和所有的爬行卡片,你能告诉小明,他最多能得到多少分吗?
解题过程:
1.这题也是简单的动态规划,以每种卡片用了多少张为状态,根据卡片的使用情况可以推算目前位置,做四维的动态规划即可。
第三题:
S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。
年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多?
解题过程:
1.这题在建兰培训时讲过,也是通过这题了解到了判断二分图的染色算法,前几天写的双栈排序也用到这个算法,第一次写还是比较难写对的。。
2.二分答案,将权值大于mid的视为有效的边,有边相连表示在不同的牢房,也就是属于二分图的2个部分。也可以用并查集来实现,并查集的实现还有2种方法,一种是带权(参考食物链那题),一种是合并关系,F[i]表示i在集合A,F[i+n]表示i在集合B(参考浙大金牌之路的说谎岛那题)。
第四题:
在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠。该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形,如上图所示,其中每个格子都代表一座城市,每座城市都有一个海拔高度。
为了使居民们都尽可能饮用到清澈的湖水,现在要在某些城市建造水利设施。水利设施有两种,分别为蓄水厂和输水站。蓄水厂的功能是利用水泵将湖泊中的水抽取到所在城市的蓄水池中。因此,只有与湖泊毗邻的第1 行的城市可以建造蓄水厂。而输水站的功能则是通过输水管线利用高度落差,将湖水从高处向低处输送。故一座城市能建造输水站的前提,是存在比它海拔更高且拥有公共边的相邻城市,已经建有水利设施。
由于第N 行的城市靠近沙漠,是该国的干旱区,所以要求其中的每座城市都建有水利设施。那么,这个要求能否满足呢?如果能,请计算最少建造几个蓄水厂;如果不能,求干旱区中不可能建有水利设施的城市数目。
解题过程:
1.这题真的是一道非常综合的题目,可以说是贪心,搜索,动态规划的结合。
2.首先对于一个蓄水站,它能供应到的城市必定是连续的区间,否则必定无解。简略证明:假设一个蓄水站X的水,最左能到达城市A,最右能到达城市B,但是它不能到达AB之间的某个城市C,那么对于其他任意的蓄水站Y,必定也不能到达C。因为X到A和X到B的路已经把C围起来了,如果能到C,必定是穿过X到A或者X到B这条路,那么从X出发也可以沿着Y到C的路到达C。 这样算法就出来了,只要求出每个蓄水站能到达的区间,其实就是一个贪心的线段覆盖问题,有点像某一年普及组的一题,貌似叫种树。按区间右端点从大到小排个序,每次选择第一个能覆盖目前未覆盖的第一个点的区间即可。
3.但是如何求出每个蓄水站能到达的区间呢。其实就是一个Flood Fill的过程,一开始我用了DFS,从每一个蓄水站出发,DFS能到达的区间,结果1个点RE,一个超时,一开始想不明白为什么,搞到数据才想明白是爆栈了。然后又换成BFS,结果还是有一个点超时。。然后就开始加一些小优化,比如不还原标记数组,让本次搜索标记的值变成目前的出发点蓄水站的编号。。把if (v[x][y]) continue; 改成 if (v[x][y]==num) continue;这样每次换一个蓄水站的时候,就不用memset把v还原成0了。这样vijos上把最慢的点
从800ms+优化到600ms+。但是学校网站还是有一个坑爹数据超时。。比如数据刚好是
9 10 11 12
8 7 6 5
1 2 3 4
这样非常有序的,那么复杂度最大就是500^3就超时了。
4.百度之后发现其实有略大于O(nm)的算法,采用动态规划,left(i,j)表示从点(i,j)出发,能到达的区间的左端点。同理求出右端点,拓扑关系不明显,用记忆化搜索实现。
但是如果只用这个是没法判断无解的情况,所以BFS不能丢了,而是一开始把所有蓄水站都加入队列,用O(mn)的时间搜一次。。最后再用贪心求解。。