大白书-第1章-算法设计基础
文章平均质量分 69
冷月残星
这个作者很懒,什么都没留下…
展开
-
枚举,搜索(中国麻将,uva 11210)
自己想的枚举还准备用个vector保存当前有哪些手牌然后讨论消去一些牌再递归求解。太糟糕了。事实上把麻将编码,然后开一个全局的34维向量,既方便消去,又不用传递参数,只需在递归前和递归后对全局变量进行修改即可。代码#includeusing namespace std;char id[35][10]={ "1T","2T","3T","4T","5T",原创 2016-10-22 15:10:59 · 373 阅读 · 0 评论 -
区间,坐标(流星,LA 3905)
一开始想到了用区间,但是只会那种开一个数组,然后vis[L+1]++,vis[R]--的那种。对double的区间没有任何办法。然后就想用离散化,枚举一下,超时= =。计算区间时还算什么直线方程,两直线交点的什么的= =。大白书上的方法还是让我大开眼界了的。对于double的区间,可以创建一个结构体,名叫事件。结构体有两个量,一个是坐标pos,另一个是类型type。每一原创 2016-10-26 20:29:42 · 543 阅读 · 0 评论 -
二分,枚举+查找(子序列,LA 2678)
一开始二分,一直WA,怀疑是因为lower_bound,找不到结果时返回n+1。所以把答案%(n+1),然后就过了。看大白书上说找不到就输出0,可是看了好几遍原题,上面没有说啊喂,怎么可以这样QAQ。大白书上有O(n)的解法,就是枚举+查找的思路,查找时优化了一下使得总时间为O(n)。典型的思路,枚举一个量,对另一个量进行查找,可以是lower_bound,O(nlogn),也原创 2016-10-26 21:50:12 · 504 阅读 · 0 评论 -
枚举(最大子矩阵,LA 3029)
感觉枚举的问题想要优化就一定要一边枚举一边维护些东西,或者要预处理之类的。记得以前做了一道题 http://blog.csdn.net/xl2015190026/article/details/52551682 唯一的不同是求周长最长。做的时候参考了这道题,也是枚举右下角,然后用单调栈维护左上角。在那题中随着j的增大,并不会影响单调栈内元素的单调性。然而在这题里,随着j原创 2016-10-27 00:59:48 · 889 阅读 · 0 评论 -
部分枚举(遥远的银河,LA 3695)
一开始没看清题,以为不一定平行。。。然后就不会了。。。看了题解写了一遍,发现求某个值最好写在一个函数里,否则有时候代码中间要出一个特例就会很麻烦,甚至要goto。写在函数里一个return就ok了。然后枚举矩形时最好不要重边,否则一行点就会算两次。重边的情况特判输出就好了。看了大白书上的代码又模仿了一遍,发现模仿别人写代码很难学到什么东西。因为你会想当然的凭着记忆去写代原创 2016-10-27 15:54:24 · 408 阅读 · 0 评论 -
部分枚举(废料堆,uva 10755)
很基础的题了,不细讲了。一道更基础的题的变种,那就是给你一个一维的数列,求最大子串和。本来是O(n^3),利用一维前缀和可以降为O(n^2),再枚举加更新又可以降为O(n)。这题就是变成了三维的情况。本来是O(n^9),利用三维前缀和可以降到O(n^6),枚举加更新又可以降为O(n^5),时间复杂度刚好够。三维前缀和用到了一点容斥原理的内容,不过都很简单了。然后有时原创 2016-10-27 19:23:30 · 333 阅读 · 0 评论 -
中途相遇法(侏罗纪,LA 2965)
几个需要注意的套路:1、给你N个东西,每个东西可选可不选,那就是2^N枚举,如果N比较小可以用一个int的每个位来表示是否选取这个物品,即位向量。如果2^N枚举,那么很有可能时间不够,因此可以使用中途相遇法,再利用map或者set,可以把时间复杂度从O(2^N)降到O(2^(N/2)logN)。2、如果要判断奇偶,特别是位向量,那么亦或运算将会是一个非常高效的方法。代码原创 2016-10-27 20:40:03 · 773 阅读 · 0 评论 -
约瑟夫环(约瑟夫问题的变形,LA 3882)
只是问最后剩下的是哪个,而没有问具体是怎么删除的,所以不需要完全模拟,只需要模拟编号就好了。一开始有n个,分别编号为 0,1,2,3,...n-1。删除第k个,即编号为k-1的那个,那么删除后剩下 0,1,...k-2,k,...,n-1。然后对n-1个物品重新编号,以便递归调用。0 n-k1 n-k+1...原创 2016-10-27 23:51:04 · 3953 阅读 · 0 评论 -
LCS,LIS(王子和公主,uva 10635)
一开始就按着LCS做。超时。还是该好好分析一下时间复杂度,O(pq)==O(n^4),只能跑规模为n==100的数据,然而n==250。竟然把LCS问题转化成了LIS问题。。之所以可以转化,那是因为两个序列内的元素都分别是不重复的。把第一个序列内所有元素根据顺序按正整数编号。不用把数据保存下来,只用编好号就OK。然后读入第二个序列,如果这个元素没有编号,说明原创 2016-10-28 00:43:44 · 396 阅读 · 0 评论 -
区间DP(Sum游戏,uva 10891)
以前做过类似的题目,几乎就一样,所以很快就做出来了。dp[i][j]代表对区间[i,j]先出手的最优解,那么枚举所有决策,区间dp一下就ok了。因为先手取完后,就轮到后手取,后手取就相当于对取完后的状态的先手取。相减就是答案。代码#include#define maxn 110using namespace std;typedef long lon原创 2016-10-28 01:04:32 · 379 阅读 · 0 评论 -
枚举,集合,动态规划(黑客的攻击,uva 11825)
很容易想到这是一个集合覆盖问题。我已开始还脑抽了,用什么强连通分量= =,他只是能中止相邻的,又不是中止一个块,但是样例能过。。。只能说自己有时候真的都没静下心来认认真真想清楚,分析好自己算法的正确性,而是瞎想觉得差不多啦就开始写代码了。WA后又想了一个错误的解法。自己应该先确定算法,然后在纸上证明正确性,然后纸上跑几个数据,再编码才好。这种瞎想出来的解法,更是要严谨,不能随便脑子里模拟几原创 2016-10-29 11:15:01 · 398 阅读 · 0 评论 -
树形DP(放置街灯,uva 10859)
前面也做了一道很像的题,那道题只要求放置的数目最少,要求覆盖的是点。在这题中,要求覆盖的是边,不但要求放着的数目最少,更要求覆盖两次的边最多。因此贪心法不再适用,最少要多少个点可以贪心求出,但是同时要求覆盖两次的边要最多却不是贪心法能够解决的,无论如何都是逃不过动态规划的。所以一开始用贪心做,做到最后发现方法是错的。看了大白书才开始用动态规划。大白书上的方法好奇怪,dp[i][j]代表原创 2016-10-31 21:19:58 · 467 阅读 · 0 评论 -
暴力,STL,哈希技术,Floyd判圈算法(计算器谜题,uva 11549)
想了老半天,只会暴力,然后就过了。。实现由三种方法,一是STL,而是哈希技术,三是Floyd判圈法。就速度而言,Floyd判圈法>哈希技术>STL。分别跑了70ms,180ms,480ms。STL真是慢的可以。就空间而言,Floyd判圈法也就是说,STL与哈希技术在空间和时间上各有千秋,但Floyd判圈法完爆一切= =。关于Floyd判圈法的一些理解。F原创 2016-10-25 00:26:01 · 2861 阅读 · 0 评论 -
水题,高效,优化(开放式学分制,uva 11078)
就是本来是O(n^2),然后从后往前枚举,顺便维护后面的最小值,就可以优化成O(n)。然后自己写了一下输入输出还是快了一点的= =。20ms/50ms。一开始输入没考虑负数,All these integers haveabsolute values less than 150000.理解成了全是整数,事实上意思是绝对值小于150000.改了就过了。这种优化思路很常见,以前原创 2016-10-24 21:56:40 · 329 阅读 · 0 评论 -
水题,优化,高效(年龄排序,uva 11462)
做了那么多题,只遇到过2个专门卡空间的题目,一个是某次比赛的,题目是啥都忘掉了,还有一个就是这个水题了。但这题主要值得学习的地方在于输入输出的优化,真的没想到自己写的输入输出能快那么多。250ms与80ms的区别。不过大白书上说的也对,在确信I/O时间成为整个程序性能瓶颈之前,不要盲目优化。至今还没遇到卡手写输入输出的题目= =。isdigit函数在头文件cctype里。输入输出函原创 2016-10-24 21:25:54 · 268 阅读 · 0 评论 -
大水题(正整数序列,uva 11384)
好吧,其实我以前做过。#includeusing namespace std;int main(){ int N; while(~scanf("%d",&N)) { int cnt=0; while(N) { cnt++; N>>=1; }原创 2016-10-22 15:17:27 · 294 阅读 · 0 评论 -
汉诺塔相关,递归(新汉诺塔问题,uva 10795)
想到了要有一个中间状态,要递归求解,但最后还是没想通。在汉诺塔问题中,小块是可以无视垫在最底下的大块的。这就为递归奠定了基础。我们只要先把大块处理好,剩下的小块就可以无视大块处理了。我们先处理最大的需要移动的块那么所有比他小的块就需要先移到备用柱上,然后才可以移动最大快。处理完这个最大快后,就可无视掉他,然后递归处理下一个更小的最大块了。而中间状态就是第一个需要移动的最大块可以移动的状态。原创 2016-10-22 17:12:57 · 452 阅读 · 0 评论 -
动态规划,记忆化搜索(分享巧克力,LA 4794)
能想到是那种枚举子集的动态规划,结果写着写着成了模拟了= =。S是位向量,代表着巧克力的集合。dp[S]是一个vector,里面装着巧克力集合S能拼出的长方形。模拟转移方程就是枚举S的子集S0,S1,然后拼出一个长方形,然后排序去重。。。果断超时。其实这种O不OK的问题,状态转移方程都是一旦有一种决策OK,那就OK。问题在于状态是啥,转移方程是啥。很容易想到dp[S原创 2016-11-03 01:04:55 · 876 阅读 · 0 评论 -
数学,计数(数三角形,uva 11401)
就自己数一数就找到规律了,代入公式预处理答案,然后直接输出。代码#include#define maxn 1000010using namespace std;typedef long long ll;ll n;ll a[maxn];ll sum[maxn];void init(){ for(ll i=4;i<=1000000;i++) {原创 2016-11-03 11:40:29 · 368 阅读 · 0 评论 -
二分+判断,最小值最大(组装电脑,LA 3971)
一开始啊,用map和priority_queue搞来搞去,各种upper_bound啊,维护单调啊什么鬼的,编码又麻烦,速度也不快,还WA。具体就是先把所有的部件都买一个最便宜的,然后放到优先队列里,每次取一个quality最小的,换成一个更大的。因为更大的反而可能更便宜(除了第一次更换一定更贵),所以要维护单调。想效率高点所以用upper_bound。弄了好久都没过,就只好用紫书大白书上的方原创 2016-10-23 20:02:40 · 365 阅读 · 0 评论 -
二分(派,LA 3635)
一开始想用讨论的方式来解决,然后发现情况非常复杂而且有些地方没法用讨论解决。只能判断且很好判断一个值是否可行,然而却没法很直观的求出最优解。那就二分吧。代码#include#define maxn 10010using namespace std;const double PI=acos(-1);const double eps=1e-4;int N,F;doubl原创 2016-10-23 23:56:10 · 336 阅读 · 0 评论 -
思路题(蚂蚁,uva 10881)
几个月前做的,再做了一遍,#include#define maxn 10010using namespace std;struct mayi{ int id; int pos; int face; bool operator < (const mayi& rhs) const { return pos<rhs.pos;原创 2016-10-24 10:46:12 · 443 阅读 · 0 评论 -
水题(填充正方形,uva 11520)
大水题,但自己却调了很久代码才过样例,因为一个下标搞错,然后debug时又找错了bug,改来改去,又把对的改成错的了。以后写代码时要仔细点,第一次写就好好注意细节,考虑清楚,而且尽量不要出现手误。改代码也要想清楚,然后改对,考虑好后续及先前的影响。自己应该是因为题目太简单所以随心所欲的做,然后就很无脑的乱改,最后调了很久才过。#include#define maxn 15usi原创 2016-10-24 11:16:29 · 548 阅读 · 0 评论 -
树(网络,LA 3902)
可能是因为做了很多树形DP,而很少做其他题的缘故,我总希望通过一遍或几遍DFS来完成预处理以及计算答案。这样的思路是十分狭隘的。一开始想让树的重心或者中心来做根,然后dfs下去,找到一个最上面的点做服务器,使得下面所有叶子都能被照顾到。但是这样的话如何判断这个点以上的叶子是否被照顾到就十分难以解决。而且已有的那个服务器还会带来额外的麻烦。自己对这种题目的应对实在是太死板了。有一个值得学习的原创 2016-10-24 15:41:21 · 258 阅读 · 0 评论 -
二分(长城守卫,LA 3177)
一看到这题,以为是数学,真的不会。事实上这是算法比赛,数学题不一定要用数学的解法。你看这题,要你找某个尽量小的值来满足一些事。简直就是明示你二分啊。而且满足不满足是连续的,因此用lower_bound。一直觉得一定是有某个公式算出答案。其实没有那么多公式化的东西,更重要的是解决问题。如果实在没有头绪,那就自己给自己出几个题目,想尽各种办法先得到答案,也许你就会找到规律,从而找到能用原创 2016-10-24 17:54:14 · 549 阅读 · 1 评论 -
动态规划,单调队列(捡垃圾的机器人,LA 3983)
自己用优化了空间的O(NC)算法写,WA是因为格式和long long。以后要仔细看输出那一栏的全部输出细节,以及输入那一栏的数据范围。还好C才100,所以没有超时。但是大白书上的方法却优化到了O(N),也就是C很大也能过,十分优秀。先将自己的O(NC)算法。dp[i][j]表示捡完第i个垃圾后剩余j空间的最短路程。如果是-1说明没有此状态。那么状态转移方程:原创 2016-11-02 21:18:33 · 1778 阅读 · 0 评论