随笔分类 - 动态规划
摘要:题意:给定一些单词,这些单词必须要是一个目标串的子串,同时给定一些串,这些串不能够出现在目标串中,其余一些串只会带来不同附加值。现在问满足前两者的情况下,要求附加值最大。数据给定一个原始串,现在要求在这些串中删除一些字符,输出在满足要求的情况下删除最少的字符并保证附加值尽可能的大。分析:这题的一个暴力的方法肯定就是对于每个字符枚举删或者不删,然后选择一种方案即可。在这个蛮力法的后面注意到其实在枚举的时候还是有很多重复计算的,比如前a个字符删除或者不删除某个字符对于后面的选择是一样的,而题目要求拥有所有的必有串,因此可以将所有的必有串建立一个ac自动机,然后根据枚举在ac自动机相应节点(状态)的
阅读全文
摘要:题意:有来自n个专业的学生,每个专业分别有ai个同学,现在要将这些学生排成一行,使得相邻的两个学生来自不同的专业,问有多少种不同的安排方案。分析:首先将所有专业的学生视作一样的,最后再乘以各自学生的数量的阶乘。排列的时候通过动态规划来处理,设状态为前i个系,一共有j个位置相邻位置来自同系,然后转移。具体见代码注释。#include #include #include #include #include using namespace std;typedef long long LL;const LL mod = (int)(1e9)+7;LL A[50];LL C[500][500]; LL
阅读全文
摘要:题意:给定一个合法的八皇后棋盘,现在给定1-10个骑士,问这些骑士不能够相互攻击的拜访方式有多少种。分析:一开始想着搜索写,发现该题和八皇后不同,八皇后每一行只能够摆放一个棋子,因此搜索收敛的很快,但是骑士的话就需要对每一个格子分两种情况进行,情况非常的多,搜索肯定是会超时的。状态压缩DP就是另外一个思路的,理论上时间复杂度是8*n*2^24,但是由于限制比较多,也就能够解决了。设dp[i][j][p][q]表示第i-1行压缩后的状态是p,第i行压缩后的状态为q,且之前一共使用了j个骑士的方案数。按照题意递推即可。#include #include #include #include #inc
阅读全文
摘要:分析:该题有2个地方要注意:所有的车要么不坐要么就坐满,这个贪心策略很容易证明是正确的,还有一点就是最后一辆车除外。#include #include #include #include #include using namespace std;const int MaX = 105;int N, K, D, S;struct Node { int ti; int qz;}seq[MaX];int dp[MaX][MaX];// dp[i][j]表示第i台车来的时候,等候人数为j时的最少开销 void solve() { memset(dp, 0xff, sizeof (dp...
阅读全文
摘要:题意:给定一个长度为N的序列,现在要求给出一个最长的序列满足序列中的元素严格上升并且相邻两个数字的下标间隔要严格大于d。分析:1.线段树由于给定的元素的取值范围为0-10^5,因此维护一棵线段树,其中[l, r]的信息表示处理完前k个数时,序列最大元素落在[l, r]区间最长上升子序列的长度。从前往后处理给定的数组,处理到第 i 号元素时,更新第 i - d 号元素,这样就能够保证最长上升的序列间隔大于d,更新是需要更新到叶子节点的,但这里更新是单点更新,每次更新的位置是该元素的值,信息就是到该点的最长上升长度。其实仔细分析可以发现这个解法其实是经典的O(n^2)的算法的改进,那个算法需要遍历
阅读全文
摘要:题意:如果一个数中的某一段是长度大于2的菲波那契数,那么这个数就被定义为F数,前几个F数是13,21,34,55......将这些数字进行编号,a1 = 13, a2 = 21。现给定一个数n,输出和n相差最小的数ax与n的差值的绝对值,其中下标x满足是一个菲波那契数。分析:该题所求真是九曲十八弯,说了那么多其实要解决的问题可以转化为给定一个x,求1-x之间有多少个F数,通过二分查找能够把下标是菲波那契数的序列求出来,之后就直接for循环找到那个最相近的数就可以了。关键是如何求解1-x之间有多少个F数,容易想到的是数位dp,但是这里不太好弄,因为10^11次方之内有50多个数,每个数又有一定的
阅读全文
摘要:题意:给定一个无向图,首先判定是否成环,然后求一条最长链。分析:成环用并查集,最长链就是个最简单的树形dp了。#include #include #include #include #include #pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int N = 100005;int n, m, ans;int set[N];int dp[N];struct Edge { int v, f; Edge() {} Edge(int _v, int _f) : v(
阅读全文
摘要:题意:给定区间[L, R]求区间内与7无关数的平方和。一个数当满足三个规则之一则认为与7有关:1、整数中某一位是7;2、整数的每一位加起来的和是7的整数倍;3、这个整数是7的整数倍;分析:初看起来确实有点麻烦,数位DP还是很容易看出来的,需要维护好三个值dp[ i ][ j ][ k ].num表示数位和为对7的余数为 j ,前面确定的数对7的余数为 k 的情况下, i 位任意与7无关的数一共有多少个;同理dp[ i ][ j ][ k ].sum 表示这些数的和为多少;dp[ i ][ j ][ k ].sqr 表示这些数的平方和为多少,这三者之间是可以递推的,详见代码。个人觉得将区间左右边
阅读全文
摘要:引用:刘聪《浅谈数位类统计问题》在信息学竞赛中,有这样一类问题:求给定区间中,满足给定条件的某个 D 进制数或此类数的数量。所求的限定条件往往与数位有关,例如数位之和、指定数码个数、数的大小顺序分组等等。题目给定的区间往往很大,无法采用朴素的方法求解。此时,我们就需要利用数位的性质, 设计 log(n)级别复杂度的算法。 解决这类问题最基本的思想就是 “逐位确定”的方法。下面就让我们通过几道例题来具体了解一下这类问题及其思考方法。SPOJ-2319Sequence题意:给定所有 K 位二进制数:0,1,…,2^K-1。你需要将它们分成恰好 M 组,每组都是原序列中连续的一些数。设 Si(1 ≤
阅读全文
摘要:题意:现给定一个字符集中一共Z个元素的环境,给出一个Z*Z的数组,表示从i到j之间的距离。给定两组字符串,分别问包含着两个字符串(给定的字符串为所求字符串的子序列不是子串)对应位的距离和值最小为多少?输出这两个字符串。分析:该题的状态还是比较好开设的,设dp[i][j]表示a串的前i个字符和b串的前j个字符被包含后的最小开销,于是动态转移方程:dp[i][j] = min(dp[i][j], dp[i-1][j] + wa[sa[i]]); 其中wa数组表示某个字符与另外一个最小花费的字符匹配,sa[i]表示a串的第i个字符dp[i][j] = min(dp[i][j], dp[i][j-1]
阅读全文
摘要:题意:给定一个数N,表示有N个位置,要么放置0,要么放置1,问至少存在一个连续的M个1的放置方式有多少?分析:正面求解可能还要考虑到重复计算带来的影响,该题适应反面求解。设dp[i][j]表示到前 i 为后导 1 个数为 j 的方案数,于是有动态规划方程:dp[i][0] = sum{ dp[i-1][0... min(i-1, M) ] };dp[i][j] = dp[i-1][j-1] 其中 j != 1单单根据这个方程时间度为O(N*M),还是不足以在有限的时间内解出该问题。通过观察我们发现方程可以简化,即后一层的和值是上一层和值的两倍减去上层的最后一个值。于是可以维护一个最后一个值得队
阅读全文
摘要:题意:给定N个点,每个点有一个停留所需的时间,和停留能够获得的满意度,有M条边,每条边代表着两个点走动所需的时间,现在问在规定的T时间内从指定的一点S到E能够获得的最大的满意度是多少?要求停留的点的满意度要依次上升。解法:这次虽然一看就是个DP,但是两个端点的处理要格外的注意,因为两个端点均可以选择路过的方式,而不是停留,因此需要虚拟出两个端点,两个端点分别表示路过起点和终点,虚拟端点与其他节点的距离也因注意连单向边,双向边就超时了。刚开始的时候打算终点不进行处理,而只是在搜索到这某个节点的时候特判一下是否为终点,对终点进行两种更新,一种是访问一种是路过,事后证明是不行的,因此路过的更新如果入
阅读全文
摘要:题意:给定一个整数串,有Q组询问,问这个串中长度为w的子串中不同的数字之和为多少,这题的动态规划感觉很有技巧性。解法:设f[i]表示w为 i 时不同的数字之和,那么考虑f[i+1]和f[i]的关系可以得知:f[i+1]就是从f[i]中去除最后一个子串后在每个串后加上一个数字的情况,因此可以得到这样的一个递推式:f[i] = f[i-1] - tail[N-i+2] + left 其中tail[N-i+2]表示长度为i-1的最后一个子串中不同的数字共有多少个,left表示所有数字中与前一个相同数字的长度大于 i 的数字还剩多少个。因此还要另外预处理出后缀不相同数字个数,和最近相同数字的长度,注.
阅读全文
摘要:题意:给定一个矩阵,矩阵上的每一点都有一个值。每次能够从任意一点开始,任意一点结束,每到一个点交替的加人的水平和剑的水平。问一共有多少种方法使得人的水平和剑的水平在最后相等。解法:f[x][y][k][0]表示在xy位置人的水平减去剑的水平的差值为k且该位置走奇数步的情况有多少种f[x][y][k][1]表示在xy位置人的水平减去剑的水平的差值为k且该位置走偶数步的情况有多少种然后维护这个数组就可以了,有一种省略了最后那个0、1的写法现在还搞不大清楚。代码如下:#include <cstdlib>#include <cstdio>#include <cstring
阅读全文
摘要:题意:给定一系列的数码管,这些数码管由3*3的图形构成,相邻的两个数码管紧挨着的一列是重叠的,现在问一共有多少种可能的情况。解法:将每个数字的可能的显示结果(能亮的地方假设都可以亮)保留起来,然后一个一个数码枚举,一个地方要注意就是相邻意味前面一个数码占用了某一个亮线,那么后面这个数码可以选择是否占用该亮线,而如果前面没用占用该亮线则后面的数码必须占用。使用f[i][j]表示到第i个字符,占用相邻列情况为j时的方案数。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <
阅读全文
摘要:题意:给定N个限定了边长范围的正方形,现在要把它们全部铺到长度固定,高度不限的墙上,一共有N种颜色一一对应使用,告诉每种颜色的单位面积价格。问铺满墙的最少开销是多少?只要长度为L的墙被覆盖了所有长度即可。解法:该题有个良好的性质为不论给定的正方形的顺序如何,都不影响最后的结果。设状态f[i][j][k]表示放置到第i个覆盖长度为j,且颜色选择为k时的最少开销。其中k是状态压缩的选择方案。那么有动态规划方程f[i][j][k] = min(f[i][j][k], f[i-1][j-p][k']) 其中p为第i个正方形合法的取值边长,k'为选择了i-1种颜色的方案,也是是k‘中有i
阅读全文
摘要:Description求区间[a,b]包含1的数量。例如区间[111,112], 整个区间包含两个数,分别为111,112,111包含3个1,而112包含2个1,所以区间[111,112]总共包含5个1.Input多组测试数据。每组测试数据包含两个整数a,b, 1 <= a<=b<=10^18.Output每组测试输出一行,表示1的数量,结果mod 10^9+7.Sample Input111 112 1 1000Sample Output5 301代码如下:#include <cstdlib>#include <cstdio>#include <
阅读全文
摘要:题意:有N件物品和V体积的背包,没见物品由所占空间和价值组成,现问第K大能够装多少物品?解法:通过增加一维信息f[i][j][k]表示占用放到第i件物品时空间为j是第k大值时多少,f[i][j][k]无法给出一个明确的转移的方程,但是我们知道第i件物品若放置的话那么能够由f[i][j-w[i]][1...K]生成K中状态,如果不放置的话就能由f[i][j][0...K]生成K种状态,分别由这2*K个状态能够得到放或者是不放的前K大,因为综合的前K大一定在放的前K大或者是不放的前K大里面。代码如下:#include <cstdlib>#include <cstdio>#i
阅读全文
摘要:题意:给定一个方格,然后告诉你一些规则,这些规则下方格中的有些位置是相冲突的。问在方格中最多能够放置多少个士兵。分析:比赛时一开始就想着用状态压缩DP来搞,不过忘了相邻三行产生关系同样可以通过添加状态的维数来解,于是想着旋转45度之后再DP,这样就只有两行发生关系,不过写起来应该不太好写。后面就用二分匹配写了该题,结果一直WA,知道比赛之后才明白原来这题不能够进行拆点构图,因为从一个点引出去的边的端点相互之间是可以连边的,这就相当于一个成环了,而有环的图又怎么划分出两个内部没有边的二分图呢?其实拆点是用求树的最小路径覆盖的问题上的,这题显然不满足。正确的解法是状态压缩DP或者是求反建图的最大团
阅读全文
摘要:题意:给定一个序列,求出这个序列中最长的一个对称的序列,并且该序列对称之中还要保持左边递增右边递减。解法:将原串进行翻转,然后求一个最长公共上升子序列,注意边界:从原串的第i位开始匹配,那么翻转过来的串就不能够匹配到[1,i-1]这个区间去,否则非法的这一段匹配结果将会是左降右增。代码入下:#include <cstdlib>#include <cstring>#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>using na
阅读全文