第三次集训——2011年3月5、6日

       今天上午讲的是搜索,主要讲的是搜索的顺序,提出了“制约力”的概念,把它按照从大到小的顺序搜索,例题有八数码问题、质数方阵。在图论方面主要讲了SPFA,竟然是中国西安交大的教授提出来的,不简单啊!

      中午去了龚秋成的生日宴会,在伊典。吃完后后看是上演奶油大战……衣服则成了牺牲品。

      下午到时已迟到一个小时,所以赶紧做。下午的题目质量比较高,都值得一写。

A题:

题目大意:能否把把N(<=50)个数分成四组,它们的和相等?

算法:搜索

优化:先对数降序排序,第一个人为放到第一组,这样就可以过了

 

B题:

题目大意:乱序给定一个数的各给位数,问是否存在一个组合,使得到的数能被99整除?

数学知识:

1.被9乘除的充要条件是各位之和能被9整除;

2.被11整除的充要条件是奇数位与偶数位和之差能被11整除;

其中1容易实现,对于2则要进行类似与Tug Of War那题,把它分成两组,且使用个数和相差不超过1;(题目数据有问题,做成了和要相等,不过关系不大)

算法1:搜索

基本思路是枚举分成两堆,看哪一堆有哪些数字,确定了思路:

dfs(dep,sum_now,lastnum),其中dep表示当前枚举第几个数字,sum_now表示当前获得的和是多少,lastnum表示上一次枚举的是哪一个数(按升序枚举)。

优化:

1.由于分的个数是确定的,所以可以估计出当前所能达到的最大和最小和(预先处理出在给定的数据中K个数能达到的最大和与最小和),这样是一个很大的剪枝

2.枚举的时候从9,8----0的顺序枚举

效率分析:

虽然理论上这个枚举的复杂度是很高的,但由于解的分布是很多的,所以有很大概率短时间内找到解;

另一种搜索:

 由于只有0-9这10个数字,所以可以预先记录出这几个数的个数,然后去枚举有多少个,这样的话DFS的深度就比较小;

 

算法2:DP

具体在枚举的时候先枚举哪一个物品,再倒序枚举个数(正序枚举则该物品能用无限次),最后倒序枚举和

 

C题

题目大意:在一个N*N(N<=500),有传送门可以传送到任意一个门(<=1000),需要一定的时间,求在给定图中的起点和终点的最短路?

算法:BFS

1.容易知道,传送门不会使用多于2次;

算法1:从起始点和终点分别不考虑做BFS做出最短路,然后枚举哪俩个门之间传送;(STANDARD)

算法2:一开始想到SPFA,但如果纯粹用SPFA,则由于传送门的存在,可能一个点会进入队列多次,效率比较低;于是想避免这个时间差,就得从等待时间开刀,而用BFS。

      如果拓展到传送门,可以知道它到达其它传送门的时间;可以不马上进行拓展,而是等待时机成熟。

      那这个时机是什么呢?

      以时间顺序枚举,必要的时候才用传送门!

      当遇到传送门时,记录下当前可以用的传送门可以达到的最少时间T;如果当前时间是t=T-1,则经由时间t的点集这些点到达其它点的最优解也就是T,这是时机成熟了。可以使用了!去更新以前还没到达的传送门,必定是达到那些传送门的最优解。

(还有一点要注意,在必须经过传送门的情况下的处理)

      这样所有的传送门的最优解都已经出来了!以后不可能再用传送门了,已没有意义,不可能得到比现在更优的解!

      这样再继续BFS,就可以得到最优解了!

 

 

D题

算法:二分

第一次二分在车上的最短时间,对于判断则不需要用二分了(效率反而低)!因为是顺序执行的,这样for一遍就可以解决了的!

 

E题

算法:后缀表达式

计算一个0-9,+,-,*的表达式的值,需要特别注意特殊的数据!

 

 

F题

题目大意:给定一个4X4的MATRIX,有黑白两种状态,变换一次可以使得5个点反色(上下左右中),求最少需要几次操作可以使得全部同色?

算法:BFS或枚举

1.对于BFS,很容易想,但状态难表示,可以用状态压缩的方法去做,但时间效率比较低;

2.这道题有很强的规律性!

每一格只能被有限个元素改变状态,所以可以枚举最终的颜色,枚举开始4个是否变色,然后从第二行开始判断上面的这个是否需要变色,如果需要则它必须变色!这样如果最后一行也满足条件,则可以去更新是有次数;

效率的差距是750MS   vs   0MS

 

G题:

题目大意:矩形覆盖的一维版本,但有10000个,且多组数据,所以N^2的算法不可以!要用NlogN的算法了!

算法是线段树,系统学习线段树后可以做此题!

下午写了二叉树版本的,对于随机数据效果较好,但是有几个点没有过。

 

H题 PRO

算法:最大堆、最小堆

算法意图很明显,就是考这个算法,但是也有点TRICK在里面。

在删除数据的时候,不是只要删ROOT就行了,一个堆中删除的在另外一个堆中也需要删除!所以要用4个数组分别记录下读入的第I个数据在堆中的位置和堆中的元素是原来的位置!复杂度提高了!

反例:

11 2

13 12

正确的应为7,可是不删除数据则是8

 花了一下午的时间终于把这道题目解决了,主要是一个调试的小错误。

关于这道题目专门放在一篇文章中详细讲解!

 

I题

算法:线段树RMQ

题目大意:求出数据中每K个元素的最大值

好久没写了,尝试了一下,框架可以写出来,但具体细节还是会有错误!

 

这次的比赛的题目很丰富!

 

USACO上的旅程有点卡了,EULER回路就有点想不通了。争取一下!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章