这次的题目比较恶心。
前四题是USACO的题目,第一题是以前做过的素数方阵,第二题是邮票,第三题是丑数,第四题是挤牛奶。
第一题是很需要技巧的搜索题。
起先想的是枚举最后一行和最后一列,再枚举第一列,主对角线和第一行,再确定副对角线,最后计算出剩余的四个,如图
3 | 5 | 5 | 5 | 2 |
3 | 4 | 7 | 6 | 2 |
3 | 7 | 4 | 7 | 2 |
3 | 6 | 7 | 4 | 2 |
1 | 1 | 1 | 1 | 0 |
最后再判断中间三行,三列是否满足,但是这样严重超时!!!
主要有以下几个原因:
1)用了<vector>容器来存贮预处理出的几个数组
type1[I]:以I结尾的各个位均为奇数的质数;
type2[I]:不包含0的质数
type2[I]:质数
type3[I][J][K]:以I开头,J为中间,K为结尾的质数
(其中均为5位质数)
原因分析:容器读取比较慢;
解决方法:用数组存取,不会太大;
2)用了get(n,k)来获取数n的第k位
原因分析:由于这是在枚举的最底层,所以要大大改进;
解决方法:预处理出一个5维数组,并且在求质数过程中把5位分离,对于新生成的只有O(1)判断;
3)都在最后一步才处理
原因分析:有些可以直接剪掉,如上面的7和下面的7不需5就可以确定下来;
解决方法:改变枚举顺序,每次把能确定的先确定下来,
枚举顺序改为1->2->4->3->6->5
新组成的第二行和第四行不许5就可以判断;
时间从10s+ ----> 5s+ ----> 2s+ ------> 1s-
最后在USACO上测得的是
看了网上的解答,还有更好的枚举顺序(加粗的可以推得)
0 20 22 23 8
13 1 17 7 15
9 10 2 11 12
14 6 18 3 16
5 19 21 24 4
时间最慢得在0.2s
启发:
1.<vector>不要随便用,当数组的长度伸缩太厉害时才使用,且要确定时间花费;
2.枚举的顺序非常重要,先枚举要紧的影响大的点;
3.要时刻剪枝;
代码太长了,就没有贴的必要了~~~
第二题:题目很好,很具迷惑性,其实就是一道BFS题!
第三题:题目很好,要保存每个素数对应的指针!
第四题:比较水~~
第五题:
题目大意:求从(x1,y1)到(x2,y2)用马走最少几步?(x,y >= 0, <= 1000000)
算法:贪心+BFS
分析:数据这么大!!!只能贪心!!!
先(3,3)方式走,再以(0,4)或(4,0)的方式走,一直走到在200(一定范围)内。
第六题:动态规划
要注意初值
ps:数据害死人哪!!题目描述害死人啊!
第七题:
题目描述:给出N(100000)堆石子,然后每次合并两堆形成新的一堆,体力为两堆的数量和,求最小体力。
分析:数据如此大,有两种方法。
1)用堆来做;
2)用单调队列来做!
第八题:
题目描述:求01矩阵中面积最大的0矩阵。
算法:动态规划
分析:
1)先预处理出某一个左边连续和右边连续的0的个数;
2)然后一次枚举每一个1(上)0(下)状态,去求出往下最多最多能搜到的数,保存左右两边的个数最少的
3)但是上面的算法近似立方,是否可以变成平方的?
设想存在一个最优解,则一定在最上边的上边有一个1(否则可以继续向上拓展大小),故只要把上面的过程先枚举列,在枚举行,一段一段处理,可以优化到平方!