随笔分类 - 算法入门经典训练指南 chapter 1 算法设计基础
摘要:在所有避难所都有至少一只队伍的情况,总移动距离最小。把队伍的位置和人都排序。会发现,对于最后一个队伍i和最后一个避难所j,Case 1:pos[j]>=pos[i],那么i是距离j最近的一只队伍,Case 2:pos[j]<pos[i],那么j是距离i最近的一个避难所。dp[i][j]表示第i个人,...
阅读全文
摘要:区间dp,两个str一起考虑很难转移。看了别人题解以后才知道是做两次dp。dp1。str1最坏情况下和str2完全不相同,相当于从空白串开始刷。对于一个区间,有两种刷法,一起刷,或者分开来刷。规定[i][i-1]为空串,这样一起刷可以归结为第二种情况。合并的时候,大的区间的次数using names...
阅读全文
摘要:难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下,对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放,虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类型还不确定。对于所有拿出来的书,最后会增加多少段只和书的种类有关。所以我们用s记录留下书的种类,等到所有...
阅读全文
摘要:和Heroes Of Might And Magic 相似,题目的询问是dp的一个副产物。距离是不好表示成状态的,但是可以换一个角度想,如果知道了从一个点向子树走k个结点的最短距离,那么就可以回答走x距离能访问到的最大结点数量。当访问了一棵子树,想要访问子树外的结点时,一定要先从子树的根结点出来。状...
阅读全文
摘要:容易想到dp[i][j]表示在第i行j个路口的开始走最大高兴值。每次可以向左走,或者向右边走,然后向北走。(或者直接往北)向左走到,状态转移为dp[i][j] = dp[i][k] + happy[i][k][j](为了方便处理,i从1开始编号,0行dp值存0)处理出前缀和,happy[i][k][...
阅读全文
摘要:为了方便打印路径,考虑从下往上转移。dp[i][j][S]表示在i行j列总和为S的方案,dp[i][j][S] = dp[i+1][left][S-x]+dp[i+1][right][S-x]方案O(2^2*n-1),结果要用long long保存。#includeusing namespace s...
阅读全文
摘要:分析:对于网格grid[i][j]如果放向上的管道,那么grid[i][k], k>j 就只能放向上的管道了。那么定义dp[i][j]表示第i行,最后一个放向左的管道是j的最大总矿量。j = 0表示全放向上,j = m表示全放向左。如果grid[i][j]要往放向上的管道的话,前提是grid[i-1...
阅读全文
摘要:分析:如果问题是要求最后一个删除的数,重新编号为0到n-1,f[n]表示答案,那么f[n] = (f[n-1]+k)%n。因为删掉下标k-1以后可以从下标k重新编号为0。在这个问题只需要推出最后三个数,然后三个数一起转移即可。单个case的复杂度O(n)#includeusing namespace...
阅读全文
摘要:分析:状态是一些有序的集合,这些集合互不相交,并集为所有区域。显然枚举集合元素是哪些是无法承受的,写出期望的计算式,会发现,当每个集合的大小确定了以后,概率大的优先访问是最优的。因此先对u从大到小排序。定义状态f[i][j]表示从j开始往后分i组的最小期望。转移是枚举划分k,则有f[i][j] = ...
阅读全文
摘要:把消灭了那些机器人作为状态S,预处理出状态S下可以消灭的机器人,转移统计方案。方案数最多16!,要用64bit保存方案。#includeusing namespace std;const int Mx = 16, maxs = 1>i&1) continue; if(canAtk[S]...
阅读全文
摘要:最长回文子序列可以用求解原串s和反转串rv的LCS来得到,因为要求回文串分奇偶,dp[i][j]保存长度,要求字典序最小,dp[i][j]应该表示回文子序列的端点,所以边界为单个字符,即i+j=len+1。这题最麻烦的地方在于字典序,我是写了个比较函数,有点暴力(常数大)。也可以反着定义,这时结点就...
阅读全文
摘要:一个区间一个区间的考虑,当前区间的决策只和上一次的末尾有关,考虑转移的时候先统计当前区间出现过的字母以及种数ct枚举上一个区间的末尾标号j,规定小于INF为合法状态,确定j之后看j有没有在当前的区间出现,如果出现则贪心选块数+ct-1,枚举当前的结尾。为了方便处理,增加一个0区间,初始为0,这样所有...
阅读全文
摘要:n的规模可以状压,f[x][y][S]表示x行,y列,S集合的巧克力能否被切割。预处理出每个状态S对应的面积和sum(S),对于一个合法的状态一定满足x*y=sum(S),实际上只有两个变量是独立的。而且有x,y等效与y,x,那么这里取max(x,y)。转移的时候枚举S的非空真子集,横着切或者竖着切...
阅读全文
摘要:如果状态定义为序号和重量的话,决策就是下一个垃圾捡或者不减,但是状态数太多了。如果只定义序号作为状态的话,决策就变成从前面的某个j一直捡到i才送回垃圾。这就变成了一个区间选最小值的问题,用单调队列维护。复杂度O(n)#includeusing namespace std;const int maxn...
阅读全文
摘要:这是一个零和博弈,最高得分只和序列以及谁先手有关。d[i][j],表示i到j的序列当前取的这个人的最高得分,转移以后状态是新的区间和另一个人取,从中取最小值。决策的最小值也可递推。#includeusing namespace std;const int MX = 101;int d[MX][MX]...
阅读全文
摘要:直接LCS是时间复杂度是O(p*q)的,但是序列元素各不相同,只要把其中一个序列映射成有序的,另外一个序列再做相同的映射,没有的直接删掉,就变成了求另一个序列LIS。#includeusing namespace std;int read(){ char c; while(c=getchar(...
阅读全文
摘要:二分,判断的时候,一个点一个点的考虑肯定是不行啦,考虑的单位是一个区间,每次左端点尽量向左边移动,右端点尽量向右,得到下次可以达到的范围,检查一下和下一个区间有没有交集。#includeusing namespace std;const int maxn = 1e5+5, maxns = 1e6+5...
阅读全文
摘要:很容易想到二分,问题在与判断一个解的可行性。贪心,时间点最多两万,可以模拟每个时间点,将事件按开始时间排序,每次优先选已经开始了的且结束时间最早的任务来做,如果某个任务在deadline之前还没有结束说明当前解不可行。R的上界不太好估计,(远远达不到总和,但是比maxw大,因为任务在时间上有重叠),...
阅读全文
摘要:贪心,假如任意给出一个序列,如果两两交换了以后会变大,那么就交换,直到不能交换为止。#includeusing namespace std;const int maxn = 51;string s[maxn];int rk[maxn];bool cmp(int x,int y){ int i ...
阅读全文
摘要:问题可以转化为草坪的边界被完全覆盖。这样一个圆形就换成一条线段。贪心,从中选尽量少的线段把区间覆盖,按照把线段按左端点排序,记录一个当前已经覆盖区间的位置cur,从左端点小于等于cur选一个右端点最大的作为这次选的区间,如果没有符合条件的,说明不可能完全覆盖。r*r会爆int...#includeu...
阅读全文