![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
动态规划
~无相~
这个作者很懒,什么都没留下…
展开
-
Garland
思路贪心有点复杂,这里直接用dp,思路清晰得多dp[i][j][0//1]表示枚举到第i个位置,已经把j个奇数填上去了(这里不包括原来就再序列里面的奇数),并且当前位置为奇数(0)/偶数(1)的代价转移方程:①:如果当前位置已经有数字了,那么就根据数字的奇偶性不同转移奇数 :dp[i][j][0]=min(dp[i-1][j][0],dp[i-1][j][1]+1);偶数 :dp[i][j][1]=min(dp[i-1][j][0]+1,dp[i-1][j][1]);*如果当前位置没有数原创 2020-08-09 14:32:44 · 183 阅读 · 0 评论 -
Wi-Fi(线段树+dp)
思路一道dp题,就是转移方程需要思考,第一种情况肯定是直接连wife,第二种情况就是放置一个wife,第二种情况的转移方程为:dp[i]=min(dp[i],dp[j]+i-k),其中如果i这个位置被覆盖了,那么是在i-k的位置放置路由器,所以花费i-k,dp[j]是i-2*k到i位置的最小的dp值。代码#include <bits/stdc++.h>using namespace std;#define int long longconst int MXN = 2e5+5;c原创 2020-06-05 14:38:52 · 207 阅读 · 0 评论 -
Array Shrinking
思路设dp[i][j]为【i,j】区间合并后的长度,a[i][j]为区间[i,j]合并后区间的值分析:如果两个相邻区间能合并,必须要区间长度都为1,并且区间的值一样,否则不能合并状态转移方程:dp[i][j]=min(dp[i][k]+dp[k+1][j]),在过程中判断一下[i,k]和[k+1,j]能不能合并,如果能就合并代码#include <cstring>#include <algorithm>#include <iostream>using原创 2020-05-15 09:10:24 · 100 阅读 · 0 评论 -
Minimum Triangulation
思路设dp[i][j]表示从编号为i的点到编号为j的点的最小解状态转移方程: dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+ijk)(其中i<k<j)代码#include <cstring>#include <algorithm>#include <iostream>using namespace std;long long dp[550][550];int main(){ int n; ci原创 2020-05-15 08:21:52 · 243 阅读 · 0 评论 -
Choosing Capital for Treeland
思路读入每一个边,并且设其权值为0,并且在连一条反向边,令其权值为1先求出顺序每个点作为根节点的时候,遍历整个子树的权值,down[i]表示从i这个点遍历它的子树的权值和我们知道每一个点到所有点的权值和为:这个点向下的权值和down[i],加上返回到父节点的边的权值,在加上父节点除了 i 这个子树的到其他点的权值和,可能将不太清楚,下面是图最后只要求出所有ans,求一下最小值就行了代码#include <cstring>#include <iostream>#i原创 2020-05-11 10:57:07 · 137 阅读 · 0 评论 -
Appleman and Tree (树形dp)
思路题意:给一个树,求分割该树使得,分割后每一个连通块中有且只有一个黑点状态定义:dp[i][0/1],dp[i][0]表示以i为根节点的树其中 i 所在的连通块没有黑点的方案数,dp[i][1]表示以 i 为根节点的树其中 i 所在连通块有黑点的方案数状态转移:dp[i][1]=dp[i][1]*(dp[j][0]+dp[j][1])+dp[i][0]*dp[j][1]因为如果 i 所在连通块有黑点,总共有三种情况,①:i 所在连通块本来就存在黑点,所以对于以 j 为根节点的子树 来说原创 2020-05-11 09:03:56 · 303 阅读 · 0 评论 -
leetcode221. 最大正方形
dp思路前言:本博客主要写给博主自己看,若想要更好题解,请点击下面官方题解链接这道题dp很巧,打破了我对状态设定的局限性,题目设dp[i][j]表示对于(i,j)这个点为右下角的正方形的最大长度。很容易写出状态方程:如果(i,j)点为1,则dp[i][j]=min(dp[i-1][j].dp[i-1][j-1],dp[i][j-1])+1,若为0,则dp[i][j]=0,不明白可以画一个图...原创 2020-05-08 16:36:37 · 73 阅读 · 0 评论 -
Magic Numbers:数位dp
思路简单的数位dp,我的dfs代码有点长了,但是是明显四个分支,结构还是很清晰的,对于每一位是否偶数,是否顶着上限,都进行分类即可代码#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int mod = 1e9+7;int dp[2...原创 2020-05-08 11:37:29 · 79 阅读 · 0 评论 -
Beautiful numbers:数位dp
思路这是一道典型的数位dp题,但是要做一些改变如果普通的思路,就是枚举一下每一位的数字,每一次存下前面所有枚举的数字的和,以及前面所有位上的数字的最小公倍数,枚举到最后一位的时候看一下是否最后的和能否整除最小公倍数,如果能就返回1,中间再用dp[pos][sum][lcm]来存下枚举到第pos位,前面数和为sum,最小公倍数为lcm的解,来作为记忆化搜索。但是以上方式太朴素,空间根本不够,...原创 2020-05-08 10:31:27 · 99 阅读 · 0 评论 -
Hackers' Crackdown
思路现预处理出每一个点和那些点相邻,状态存入link再对于选取电脑状态为i(例如i=2,表示选取了第二个电脑),处理出i这个状态能覆盖的所有点存入cover再进行dp,枚举所有的点的选取状态,为i,再枚举一下i的所有子集为j,如果j能把所有点覆盖,就更新dp[i]=max(dp[i],dp[i^j]+1),i ^ j表示j的补集代码(转载)#include <stdio.h&g...转载 2020-04-27 10:17:01 · 152 阅读 · 0 评论 -
Headmaster's Headache
思路这里参考了一位大佬的blog,我这里只是简单说一下我的理解首先这道题学科数量很少,所以可以用状态压缩做这道题,但是这里学科要两个老师教,所以我们把一个学科分为2个相邻位,比如把原本第一个学科1,分为第1位和第2位,这样只要所有位都为0的时候,就表明所有学科都教完了接下来就是把那些已经在学校,必须用的老师给用了,统计下所有花费,更新一下状态,这道题的输入有点不舒服。再把那些应聘的状态给...转载 2020-04-27 09:38:07 · 307 阅读 · 0 评论 -
Happy Matt Friends
思路01背包加状态压缩dp,dp[i][j]表示枚举到i的时候,状态是j的时候的方案数,dp[i][j&a[i]]+=dp[i-1][j].dp[i][j]+=dp[i-1][j];最后统计一下所有的方案数即可AC代码#include <cstring>#include <iostream>#include <algorithm>using...原创 2020-04-24 11:39:22 · 81 阅读 · 0 评论 -
Corn Fields P(状态压缩dp)
思路思路:典型状压dp,题目要求:求方案数限制:每一行不能连续为1,相邻行不能同一列同时为1,在土地为0的地方不能为1做法:设dp[i][j],表示枚举到第i行,当前状态为j的方案数,状态转移方程:(dp[i][j]+=dp[i][k])(其中j,k满足题目要求)要求判断:连续不能为1的,枚举所有位,只要记一下上一次1出现的位置,出现1的时候看一下是否和上一次1的位置相邻即可,不能相邻...原创 2020-04-24 10:47:08 · 146 阅读 · 0 评论 -
Compatible Numbers(位运算)
思路题意:从数组中找到与a[i]相与值为0的数,没有则输出-1如何找到所有与x相与等于0的数呢?首先 x按位取反得到y,此时y&x=0,但是y中为1的位如果改为0,也是与x“相容“的,因为y中为1的位在x同一位上是0,所以通过枚举y中位值位1的点改为0还是保持1可以得到所有与x”相容“的数做法:我们先用b数组存下b[i]和a数组中哪一个数相与:即b[i]=a[j]则表示 i&...原创 2020-04-24 09:56:34 · 920 阅读 · 1 评论 -
Alibaba(特别区间dp)
思路这题目的区间dp很特别,设dp[i][j][2],表示走完区间[i,j]并且最后站在某一个端点的最小时间,其中0表示左端点,1表示右端点那么dp[i][j][0]可以从dp[i+1][j][0]转过来,要加上pos[i+1]-pos[i],即 dp[i][j][0]=dp[i+1][j][0]+pos[i+1]-pos[i]也可以由dp[i+1][j][1]转过来,即dp[i][j...原创 2020-04-20 16:46:28 · 151 阅读 · 0 评论 -
Queries for Number of Palindromes
思路定义dp[i][j]表示及区间[i,j]内的回文子串的个数,转移方程如下:dp[i][j]=dp[i+1][j]+dp[i][j−1]−dp[i+1][j−1]+isPar[i][j]其中isPair[i][j]表示s[i~j]是否为回文串利用容斥原理其他的都是和最长回文子序列的dp过程一样了代码#include <iostream>#include <c...原创 2020-04-20 13:56:20 · 167 阅读 · 0 评论 -
Brackets(Poj2995)
思路这个就是和回文很想的dp问题,只是多了一种情况需要考虑,就是 A B 都是合法括号,那么A+B也是合法括号,所以只要在dp的时候,吧区间分割,枚举一下分割的中点即可。代码#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int N...原创 2020-04-20 13:06:03 · 151 阅读 · 1 评论 -
Two Rabbits
思路代码#include<iostream>#include<algorithm>#include<cstring> using namespace std;const int N=1005;int dp[N][N],a[N]; int main(){ int n; while(~scanf("%d",&n)&&...原创 2020-04-20 12:38:31 · 159 阅读 · 0 评论 -
Dima and Salad(dp+思维转化)
思路题目要求选出来的物品满足 sum( a[i] )=ksum( b[i] ),移动到同一边 ,sum( a[i] )-ksum( b[i] )==0.令c[i]=a[i]-k*b[i],题目转化为从 n 个 体积为 c[i] , 价值为 w[i] 的物品中取出若干物品,使得 sum( w[i] )最大,并且 sum( c[i] )==0,我们令 dp[i][j]表示枚举到第i个物品时候, ...原创 2020-04-20 11:18:51 · 259 阅读 · 0 评论 -
Pay the Price
思路其实本题dp是没有多难的,就是在读入哪一个地方有坑,设dp[i][j]为i这个数字由j个数字组成的方案数量,预处理出来,然后根据不同的要求取求和即可,即没有数量要求就是sum(dp[i][j]),(0<j<=i);有固定数量要求的就是sum(dp[i][j]),(0<j<=k)k为要求组合数小于的数量,有区间数量要求的就是sum(dp[i][j]),(l<j&...原创 2020-04-17 20:45:36 · 244 阅读 · 0 评论 -
Space Elevator
思路一个贪心加dp问题,首先这道题的限制是对于每一个物品有个限制高度,所以我们在用01背包解决问题的时候,不仅仅只考虑能不能放进去,也要考虑是不是超出了高度,而这样就要求我们要在考虑01背包的思维的时候,加一个顺序进去,这就是贪心,从低到高取顺序考虑物品,优先考虑限制低的物品,这样就可以对物品按照限制从低到高排序,当然这之前要把多重背包二进制转化成01背包,然后01背包dp即可,最后遍历一下所有...原创 2020-04-17 13:30:15 · 309 阅读 · 0 评论 -
D - Arpa's weak amphitheater and Mehrdad's valuable Hoses
思路是一个分组背包问题,中间用并查集来进行分组即可代码#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;typedef long long ll;const int N=1005;const i...原创 2020-04-17 12:08:55 · 99 阅读 · 0 评论 -
Defense Lines(dp+二分)
思路(好久不写字,丑点但是很详细)AC代码(700ms)#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N=2e5+5;const int INF=0x3f3f3f;int a[N];int L[N],R[N];in...原创 2020-04-17 10:36:30 · 189 阅读 · 0 评论 -
Wavio Sequence(dp+二分)
思路是一个最长上升子序列题,这里要dp两边,一个从前往后,一个从后往前,每个点的值就是左右两边长度的最小值*2-1。当然,这里的dp是要用二分的,朴素版的过不去。代码#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N=1e5...原创 2020-04-17 09:07:06 · 228 阅读 · 0 评论 -
Coins
思路一个裸的多重背包问题,然后就是一个01背包的求方案数问题,只不过这里统计的是那些取值是有方案的。代码#include <iostream>#include <algorithm>#include <vector>#include <cstring>using namespace std;const int N=100000;in...原创 2020-04-13 11:46:33 · 322 阅读 · 1 评论 -
Cut Ribbon
思路这是一道完全背包题,但是和一般的不一样,这里f[j]是恰好长度为j的时候的解,而不是一般的不超过j,所以在相同的转移方程的基础上要改变限制,只要加上一个判断,判断一下f[j-a[i]]是否存在即可,或者把所有f初始化为-INF,也可以得到答案,最后判断一下f[m]是否为正数即可判断是否有解,以上的改变如果不做,就会变成求不超过j的解,因为有些j的取值是不存在的,所以不经过判断或者认为去除就会...原创 2020-04-13 11:30:08 · 247 阅读 · 0 评论 -
Cash Machine
思路一个典型的分组背包,这里要用二进制优化转化成01背包代码#include <iostream>#include <algorithm>#include <vector>#include <cstring>using namespace std;const int N=100000;int f[N];int n,m;vecto...原创 2020-04-13 10:54:45 · 144 阅读 · 0 评论 -
Charm Bracelet
思路纯01背包代码#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int N=20000;int f[N];int n,m;int w[N],d[N];int main(){ while(cin >> n...原创 2020-04-13 10:32:20 · 146 阅读 · 0 评论 -
Writing Code(详细)
思路代码#include <iostream>#include <algorithm>using namespace std;const int N=1010;int n,m,b,mod;long long sum;long long f[N][N],a[N];int i,j,k;int main(){ cin>>n>...原创 2020-04-13 10:19:16 · 425 阅读 · 0 评论 -
Bone Collector
思路就是一个多个测试的01背包代码#include <iostream>#include <cstring>#include <algorithm> using namespace std;const int N=1010; int n,m;int v[N],w[N];int f[N];int main(){ int T; ...原创 2020-04-13 09:27:44 · 80 阅读 · 0 评论 -
CF10D - LCIS
思路就是最长公共子序列和最长递增子序列融合一起dp[i][j]:表示的是以b[j]结尾的,和a的前i项匹配出来的最长递增公共子序列的长度状态转移:①不包括a[i],也就是公共子序列中没有a[i],即dp[i-1][j]②包括a[i],那么必须要满足a[i]==b[j],在这个基础上,我们枚举一下k(k<j)使得b[j]>b[k],取所有k中dp[i-1][k]最大的一个以上...原创 2020-04-10 19:40:54 · 128 阅读 · 0 评论 -
超级楼梯
思路线性dp,两个状态,加起来即可。代码#include<iostream>#include<cstring>#include<algorithm>using namespace std;int dp[50];int main(){ int t; cin >> t; dp[1]=1; for(int i...原创 2020-04-10 18:47:00 · 65 阅读 · 0 评论 -
The Triangle
思路就是一个经典的金字塔dp问题,每次有两个状态可以转化过来,去一个最大就可以了代码#include<iostream>#include<cstring>#include<algorithm>using namespace std;int dp[110][110];int a[110][110];int n;int main(){ c...原创 2020-04-10 18:45:38 · 72 阅读 · 0 评论 -
CF:D. Slime
思路如果所有的数都是正数,那么我们可以用最小的数来减去其他的数,只留下一个正数来最后减去他们的和即可,如果全是负数,那么就找最大的数,来减去其他的负数,留下一个负数,让和来减去那个负数即可,如果有正有负,那么可以让负数减去周围的正数,只留下一个正数,最后减去所有剩下的负数即可,n=1,2的时候特判。代码#include <bits/stdc++.h>#define maxn ...原创 2020-04-10 11:36:59 · 150 阅读 · 0 评论 -
Maximum sum
思路分别从左往右和从右往坐开始求最大连续子序列和,之后枚举一下求最大值即可,这里读入数据不能用cin ,会被T,我是服了。代码#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int N=50000+5;const int INF=...原创 2020-04-10 10:03:09 · 364 阅读 · 0 评论 -
Curriculum Vitae
思路因为序列只有0和1,如果要求满足0都在1前面的序列最长长度,就等价于求一个中间没有递减的序列的最长长度(一个数可以等于前面的数,但是不小于),这样只要把LIS的判断条件改一下就可以了。代码#include <cstring>#include <iostream>#include <algorithm>using namespace std;co...原创 2020-04-10 08:44:58 · 510 阅读 · 0 评论 -
试题 算法提高 矩阵乘法
思路非常经典的一道题,是紫书上的题目,动态规划,f[i][j]表示起点为i,终点为j的区间合并的最小值,我们枚举一下区间长度,因为大的区间的值是由小的区间来递推出来的,所以区间长度从小到大枚举,然后枚举一下起点,在枚举一下形成[i,j]的区间的最后一次矩阵合并时那两个区间的矩阵即可,这里可能爆int,所以用long long;代码#include <cstring>#inclu...原创 2020-04-08 15:43:56 · 493 阅读 · 0 评论 -
试题 算法提高 和谐宿舍2
思路设f[i][j]表示覆盖到i(i这个矩形已经被覆盖)的时候用了j块木板的面积最小值,然后我们枚举一下最后一块木板覆盖的矩阵是从k到i的(包括k和i矩形),转移方程:f[i][j]=min(f[i][j],f[k-1][j-1]+max*len),其中max表示的是k到i矩形里的高度最大的值,len是i-k+1,所以我们还要预处理出来区间最大值,这里就可以用线段树来实现.代码#includ...原创 2020-04-08 12:59:56 · 550 阅读 · 0 评论 -
试题 算法提高 秘密行动
思路简单动态规划,设f[i][j]为爬完第i层需要的最短时间,j=0的时候表示爬完第i层的时候,没有经过跳跃,1表示经过了跳跃代码#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int N=10010;const int INF=...原创 2020-04-08 10:25:28 · 387 阅读 · 0 评论 -
试题 历届试题 对局匹配
思路代码#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int N=100010;int cnt[N];int main(){ int n,k; cin >> n >> k; fo...原创 2020-03-31 15:19:38 · 160 阅读 · 1 评论