合集-动态规划dp
摘要:原题链接 太妙了,请移步题解区,有用数学归纳法做的,也有用找规律做的 L型积木一定是成对出现的 code #include<bits/stdc++.h> using namespace std; const int mod=1e9+7; long long dp[10000005]={0}; int
阅读全文
摘要:前景导入 当 \(t\in [1,2]\) 时,本题如何求解? 答:树形dp 设 \(f[i]\) 为以 \(i\) 为根的树,根节点的晶蝶已消散且儿子节点的晶蝶还未被惊动,能获得的最大晶蝶数。 则有状态转移方程 \(f[i]=(\sum f[u])+max(a[u])\) ,其中 \(u\) 为
阅读全文
摘要:原题链接 题解 细节很多的树形dp,请看代码 code #define ll long long #include<bits/stdc++.h> using namespace std; ll sit[100005]={0}; ll f[100005]={0}; vector<ll> G[10000
阅读全文
摘要:原题链接 题解 一开始我想的是每个节点要么建,要么不建,可是这样一来不好转移,因为有如下情况(黑色代表建站) 于是我们换一个角度思考,我们发现一个点要能通网,有三种情况: 1.自己建站 2.儿子建站 3.父亲建站 Code #define ll long long #include<bits/std
阅读全文
摘要:原题链接 题解 巧妙的背包问题 我可以用按顺序遍历城堡,顺便表示出遍历到当前城堡时用掉了多少兵力,这样是可以穷尽所有兵力派送情况的 同时把这个城堡里的敌方兵力升序排序,然后遍历,表示为了消灭所有兵力小于等于ta的敌人所加的分 code #include<bits/stdc++.h> using na
阅读全文
摘要:原题链接 题解 设 \(sum\) 为总能力 则若 \(sum\) 是 \(F\) 的倍数 \(\to\) \(sum\ mod\ F=0\) 根据加法求模的特性,我们可以设 \(dp[i][j]\) 为 加上第 \(i\) 个元素后, 模为 \(j\) 的方案数 转移方程移得 注意一个细节:按照遍
阅读全文
摘要:原题链接 题解 太妙了 如果能出去,那么出去的时间一定为让我出去的那个垃圾掉落的时间,且在此之前我所在的高度能撑到我垃圾掉落 如果出不去,我肯定一直呆在井底不动 所以我们可以以高度为变量 设每个高度能撑到的最久的时间 而每个垃圾在拿到的一瞬间要么吃要么搭,所以我们穷举,两个都要,如果搭,那么搭上去的
阅读全文
摘要:原题链接 题解 遍历主件,和还剩下多少钱的情况下,最多有五种购买决策 1.不买 2.买主件 3.买主件+附件1 4.买主件+附件2 5.买主件+附件1+附件2 如果当前的钱够买,那就买买看,然后加上剩下的钱能买的最大值 code #include<bits/stdc++.h> using names
阅读全文
摘要:原题链接 题解 我们发现,当前的决策会影响未来的结果,因此我们把当前的决策存下来,这样等未来要用的时候就有的转移了,如果未来由多个状态决定,那就现在把那些状态都记录下来 我们发现,一个点如果能被吸收,那么其左边或右边的一个区间的点都肯定被吸收了,所以我们记录 \(f[i][j]\) 表示区间 \([
阅读全文
摘要:原题链接 题解 等价于线性代数中求最大无关组的大小 code #include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n; cin>>n; int a[105]={0}; fo
阅读全文
摘要:原题链接 题解 对于每个容量,当前组 \(i\) 而言,放的决策有 \(size(i)+1\) 种 code #include<bits/stdc++.h> using namespace std; struct unit { int w,v; }; vector<unit> G[1005]; in
阅读全文
摘要:原题链接 题解 代码量小的离谱,思维难度大的离谱 对于两个原本不相邻的同色区域块,历经千辛万苦碰面的场景,我们可以描述成右边的区域块为左边的区域块消除的时候增添了长度 设 \(dp[i][j][suf]\) 代表消除区域 \([i,j]\) 同时该区域的 \(j\) 增添了长度 \(suf\) 但是
阅读全文
摘要:原题链接 题解 话说dalao们是怎么做这么快的?? 问从含有字符串的背包中取出一些字符串(每个背包只能娶一个),问能拼凑出给定字符串的最小代价 由于这里的拼凑是有顺序的,即如果b能拼上的是中间一块,那么a一定拼的是前边一块,这种拼凑让人想到了背包 这里是字符串的背包,其实是一样的,先判断能不能放进
阅读全文
摘要:原题链接 题解 当你直到贪心不可行的时候就要用dp了 code #include<bits/stdc++.h> using namespace std; int ans=2e9; vector<int> G[10005]; int dp[100005][55]={0}; void ss(int no
阅读全文
摘要:原题链接 题解 1.选择一个区间,然后加上其和的 \(c-1\) 倍,所以我们要选中区间和最大的那个 2.然而由于倍数可能为负,即 \(c<=0\) ,所以这时我们要尽可能选和小的 3.由于最多选一次,意味着也可以不选,所以dp的时候不选就可以赋零 code #include<bits/stdc++
阅读全文
摘要:原题链接 审题 1.连续子序列:子序列必须连续 2.最小长度为1 3.子序列之间至少隔一个数 题解 令 \(presum[i]\) 代表i及其之前的最大前缀和 则第一步更新令 \(presum[i]\) 为必须包括i的最大前缀和,第二步更新令其为i及其之前的最大前缀和。 sufsum同理 最后枚举断
阅读全文
摘要:原题链接 题解 这里和线性最大两段子段和不同,没有子段之间必须间隔一米,所以处理方式略有不同 code #define ll long long #include<bits/stdc++.h> using namespace std; ll a[200005]={0},pre[200005]={0}
阅读全文
摘要:原题链接 题解 1.我们没法遍历每个区间然后找出他们的最小值,所以我们考虑每个元素对答案的贡献 2.对于每一个元素来说,它的贡献等于它所在的区间长度乘上自身的值,这里的区间指的是以它为最小值的区间 3.以每个元素为最小值的区间要怎么求呢?我们将其转换成求左边第一个小和右边第一个小 对于这种问题(求序
阅读全文
摘要:原题链接 题解 1.当没有花费限制的时候,我们可以将其抽象为简单的背包问题 2.如果有了花费限制,那么我们就再加一维条件 3.如果一个线段能用,那么它前面一定是铺满的,那我们令线段按起点排序,通过某种运算,保证放这个线段时,前面的线段组成是最优的 比如在 \(i\) 点结尾位置花费 \(j\) 所达
阅读全文
摘要:原题链接 题解 太巧妙了!! 层加式? code #include<bits/stdc++.h> #define ll long long using namespace std; ll a[100005]={0}; int main() { ll t; cin>>t; while(t--) { l
阅读全文
摘要:原题链接 题解 1.异或是01变1,11变0,或是01变1,11变1,所以或的越多(即分的组越多),结果越大 2.我们令x=x+1,这样小于等于x的 问题就变成了小于x 的问题,这里我们采用逼近答案的方法。 3.对于某一位而言,如果有奇数个元素在这一位上是1,那么不管怎么分,最后的结果肯定是1,如果
阅读全文
摘要:原题链接 题解 1.看到数据范围很小,所以我们可以穷举 如何穷举呢? 三个方向的背包dp,令 \(dp[i][j][k]\) 来表示 三边长度为 \(i,j,k\) 时能否达到,然后最外面一维是所用的木板 由于她想用所有的木板 所以 \(k=total-i-j\) ,所以可以变成两维 注意这里的背包
阅读全文
摘要:原题链接 这道题让我对状态转移的理解更深 题解 1.对于任意一个点,不是在休息就是在锻炼,因此可以设 \(dp[i][j]\) 又因为疲劳值对答案也会有影响,或者说,当确定时间,决策,疲劳值时,所走过的路的最大值是可以确定的 所以再加一维 code #include<bits/stdc++.h> u
阅读全文
摘要:原题链接 题解 1.二分+dp code #include<bits/stdc++.h> using namespace std; string name[1000005],dp[1000005],st[1000005]; int main() { string s; cin>>s; int cnt
阅读全文
摘要:原题链接 题解 1.看到拼接,有种背包dp的感觉 所以方法1,暴力背包dp \(Code1\) #include<bits/stdc++.h> using namespace std; int vis[200005]={0}; vector<string> a; int main() { strin
阅读全文
摘要:原题链接 这真的是橙题吗 题解 读题,每个材料都有用或不用两种选择,然后n的数据范围也很小,所以考虑二进制dp (别管我为什么不叫状态压缩) 遍历 0 到 \(2^{20}-1\)(十进制下),如果存在互相矛盾的1,代表这个状态不能用 code #include<bits/stdc++.h> usi
阅读全文
摘要:原题链接 题解 1.把字符串倒过来,记作 \(S_1\) 其最大公共子串是回文串,所以这部分可以不用求,字符串长度减去最大公共子串的长度就是答案 2.怎么求最大公共子串的长度呢? 假设我们已经知道字符串a和字符串b及其所有子串的lbs,此时往字符串b末尾添加一个字符c变成字符串b1,而字符串a中以最
阅读全文
摘要:原题链接 题解 1.考虑到每个牛只有选或不选两种选择,这样暴力搜索的思路便产生了 2.还是上面的思路,怎么优化呢? 想想背包数组,其下标是什么?是体积 其值是是什么?是价值 是在体积相同的情况下选择价值最高的,本题也是,最优解一定是相同智商里情商最高的 3.价值和体积都是负数,怎么解决? code
阅读全文
摘要:原题链接 题解 第 \(i\) 朵花的选择范围为 \([i,m-n+i]\) ,而它一定是由第 \(i-1\) 朵花的某种选择继承而来的 code #include<bits/stdc++.h> using namespace std; int n,m; int dp[105][105]={0},p
阅读全文
摘要:原题链接 题解 1.常见思路: \(dp[l][r]\) 为把 \([l,r]\) 内的元素全部消掉留下一个元素的值,然后枚举中间点 但是这样内存不够,观察到 \(a_i \in [1,40]\) ,我们可以换个思路,由于区间 \([l,r]\) 内全部消掉留下一个元素的值 \(v\) , 其中 \
阅读全文
摘要:原题链接 题解 easy.ver::只能朝一个方向走,还剩奇数个格子时先手获胜 medium.ver: 令 \(u_i\) 为根节点,这样就只能朝子节点的方向走,设 \(dp[now]\) 为当以now为根的树,且now节点已经有一颗棋(其子节点均还没有)时,先手必胜1还是必败0,状态转移方程:\(
阅读全文
摘要:原题链接 题解 1.每一天只有二种决策,第一是不买,第二是当天买过几天抛 第二种决策等价于当天买入第二天抛,原理如下 对于一只股票,我们在第 \(i\) 天买第 \(j\) 天卖,其效果可以被看为在第 \(i\) 天买,第 \(k\) 天卖 \((𝑖≤𝑘≤𝑗)\),当天再买回来,第 \(j\)
阅读全文
摘要:原题链接 题解 注意数据范围 1.我们不知道要在哪些地方建站,所以考虑都遍历一遍 2.如果一个地方 \(i\) 要建站,那么在它前面且离它最近的一个站,一定建在所有右端点大于 \(i\) 的区间中,左端点最大区间里 所以我们令 \(dp[i]\) 表示为在 \(i\) 建立一个站,且和 \([1,i
阅读全文
摘要:原题链接 题解 code #include<bits/stdc++.h> using namespace std; #define ll long long const ll mod=1e9+7; ll a[7][7]={0},e[7]={0}; void cf1() { ll tem[7]={0}
阅读全文
摘要:原题链接 题解 观察到h不大于1e5,于是拿h做文章 如果想要在第 \(i\) 个月的幸福值达到 \(j\) 那么第 \(i-1\) 个月的幸福值一定能达到 \(j-h_i\) 而且 \(cost_{[i-1][j-h_i]}+c_i \leq x·(i-1)\) 记得用滚动数组优化,因为这里 \(
阅读全文
摘要:原题链接 题解 1.请务必读清题干意思 2.如果以最顶端积木的位置为状态,是可以穷尽所有情况的,则状态为 \(dp[i][l][r]\) ,最顶端第 \(i\) 层只在区间 \([l,r]\) 内连续放置积木有几种方法 3.状态转移方程 $dp[i][l][r]=\sum_1^l \sum_r^m
阅读全文
摘要:原题链接 题解 设 \(E_i\) 为树根到高度为 \(i\) 的点的期望用时 \(P_i\) 为 \(i-1\) 到 \(i\) 时,掉下去概率 则有 \(E_i=E_{i-1}+1+(1-P_i) \cdot 0+ P_i \cdot E_i\) 式子解读: 当我花一单位时间到i点时,有p的概率
阅读全文
摘要:原题链接 请跟着我假设的情景走: 我现在随便拿一块砖 \(A\) 放在地上,接着我又拿了一块砖 \(B\) 请问,\(B\) 是放在 \(A\) 上面好,还是放在 \(A\) 下面好? 分类讨论 \(b.v<a.w ,a.v \geq b.w\) 此时 \(B\) 能且只能放在 \(A\) 的上面,
阅读全文
摘要:原题链接 题解 定义 \(dp[i]\) 为今天有 \(i\) 元钱花时,明天卖能纯赚多少钱(这里有一个递归的思想,不需要考虑 \(dp[k-a[i][j]]\) 能否买得起今天的产品) 如果 \(dp[i-1]=k\) 那么 \(dp[i]\geq k\) ,所以存在一个 \(i\) 使得钱全部花
阅读全文
摘要:原题链接 题解 关键因素:调和级数 \(\frac{1}{n}+\frac{1}{n-1}+...+\frac{1}{2}+\frac{1}{1}\) 可以近似看成 \(log(n)\) code #include<bits/stdc++.h> using namespace std; #defin
阅读全文
摘要:原题链接 题解 对于区间,其末尾,要么没有操作过,要么被最后一个元素往前操作,要么被前面的元素往后操作 code #include<bits/stdc++.h> using namespace std; #define ll long long ll a[300005]; ll dpl[300005
阅读全文
摘要:原题链接 题解 1.先想想能不能暴力? 发现好像不行,因为不知道哪些元素组合的按位与能恰好有k个1 2.观察数据范围,发现 \(a_i \leq 63\) 也就是说,按位与的结果最大不会大于63 ,即 6 位 1 ,这暗示着我们可能可以从这里入手,即遍历所有按位与的情况,然后判断每种有k个1的按位与
阅读全文
摘要:原题链接 题解 n+1会发生什么? 答案可不可以用结尾的状态来定义? 可不可以用结尾的状态来转移? code #include<bits/stdc++.h> using namespace std; #define ll long long const ll mod=998244353; ll dp
阅读全文
摘要:原题链接 题解 1.改变座位之后,保持人的相对顺序不变一定使答案不劣 2.\(n\) 不是很大,因此可以考虑 \(O(n^2)\) 的做法 3.令 \(dp[i][j]\) 为第 \(i\) 个人移到位置 \(j\),且 \([1,i-1]\) 的人都已经移到了最优位置时的最小花费,\(index[
阅读全文
摘要:原题链接 题解 n很小,所以直接二维dp,判断每个事物在每个时刻取出来的最小值 注意当所以时刻都为200的时候,最晚可以在300取 code https://codeforces.com/problemset/problem/1437/C
阅读全文
摘要:原题链接 题解 把(当作+1,)当作-1,我们可以得到这样的图像 易得要保证翻完之后整体的合法性,\([l,r]\) 内的左右括号数量要相等,在图上看就是 \(pre[l-1]==pre[r]\) 相等 一个合法括号,要保证所有的 \(pre[i]\) 不小于0,因此反过来之后,最小的 \(pre[
阅读全文
摘要:原题链接 题解 我一开始想遍历每一个点,然后求出能和它配对的点的权值,但是参考菊花图,这样的速度太慢,所以考虑用一个点表示多个配对,于是发现每个点都可以作为配对的中间点 code #include<bits/stdc++.h> using namespace std; const int mod=1
阅读全文
摘要:原题链接 题解 1.alice的策略一定是从小到大一个一个拿 2.为了让alice拿不到某特定值的蛋糕,bob需要在alice拿它之前把它拿完 3.在最优策略中,bob一定可以从小拿到大 4.设此时bob要拿完第 \(i\) 类蛋糕,该类蛋糕个数为 \(k\) 则拿完这个蛋糕bob还有 \(i-k-
阅读全文
摘要:原题链接 题解 每个点要么喂,要么不喂,我们令 \(dp[i]\) 为前 \(i\) 个步骤最多能喂养多少猫,易得 \(dp[i]\) 是单调不减的 我们再维护每个点被包含的区间里的最左端 \(l\) 这样一来 \(dp[i]=max(dp[i-1],dp[l-1]+sum)\) 可是如何维护每个点
阅读全文
摘要:原题链接 题解 尽量直观地理解单调队列的作用 首先,对于合法的一段,有如下性质 A 满足: 当前的最高温度大于等于前面的最大的最低温度 该性质对于段内每一个数都满足,所以对于第 \(i\) 天,我们可以找其前面的第一天 \(j\) 的最低温度大于 \(i\) 的最高温度,同时还要满足 \((j,i]
阅读全文
摘要:原题链接 题解 首先,考虑接下来往哪颗树飞是很困难的,因为当前的决策会影响之后的决策 但是如果考虑到达当前树从哪里飞过来就比较好了,因为无后效性 接着我们可以暴力做法,遍历每棵树从前 \(k\) 个树飞过来的值,然后取最小的那个,但是这样显然会超时,所以我们优化一下 有哪些值得被优化的地方?--有很
阅读全文
摘要:原题链接 题解 暴力dp: 遍历 \(i,j,k\) ,\(dp[i][j]=\max(dp[j][k])+v_i\) 其中 \(x_i-x_j\geq x_j-x_k\) 优化: 对于 \(j\) 来说 ,随着 \(i\) 越大, \(k\) 可以越小,因此省去了遍历一层 \(k\) ,而是维护每
阅读全文
摘要:原题链接 题解 暴力:二进制表示所有状态 为了减少重复运算:设计一个数组,代表 \(x\) 为某值的时候最小的 \(y\) 但是还需要知道吃了多少个:再加一层状态不就好了 code #include<bits/stdc++.h> #define ll long long using namespac
阅读全文
摘要:原题链接 题解 在日期上设计 无后效性 但是 \(1e9\) 发现真空点去掉对答案也没有影响,故对所有线段的端点离散化处理,然后再做无后效性处理 code #include<bits/stdc++.h> #define ll long long using namespace std; const
阅读全文
摘要:原题链接 题解 看到数据范围,想到二进制表示所有已经上去的人的集合的最小乘坐次数,做法为遍历所有子集再遍历所有子集 时间复杂度 \(\sum_{k=0}^n C_n^k 2^k =\ O(3^n)\) 太高了 考虑优化,对于同一个集合、同样最小乘坐次数,总有电梯有空位,而空位越大的乘坐配置越优 依照
阅读全文

浙公网安备 33010602011771号