
【动态规划】
文章平均质量分 93
欣君
追寻那如樱花般的绚烂
展开
-
2022牛客多校#6 C. Forest
2022牛客多校#6 C. Forest原创 2022-08-07 13:41:10 · 455 阅读 · 3 评论 -
2020牛客多校#3 J - Operating on the Tree 树形DP+组合数学
题目链接:https://ac.nowcoder.com/acm/contest/5668/J这题来是2014北京区域赛的原题。介绍的做法与官方题解不同,思想来自HDU大佬的题解。设dp_numi,jdp\_num_{i,j}dp_numi,j表示以节点iii为根的子树内,根节点iii被第jjj位选取且对答案产生贡献的总方案数设dp_deli,jdp\_del_{i,j}dp_deli,j表示以节点iii为根的子树内,根节点iii被第jjj位选取后,对其子节点的贡献影响(由于节点iii被选取了,原创 2020-07-23 19:28:10 · 259 阅读 · 0 评论 -
2020牛客多校#2 G - Greater and Greater 动态规划+bitset优化
题目链接:https://ac.nowcoder.com/acm/contest/5667/G 思路与官方题解相同,只是描述方式不同。 设dpi,jdp_{i,j}dpi,j表示子序列[Ai,Ai+m−j][A_i,A_{i+m-j}][Ai,Ai+m−j]与子序列[Bj,Bm][B_j,B_m][Bj,Bm]是否匹配,即∀k∈[0,m−j],Ai+k≥Bj+k\forall k \in [0,m-j],A_{i+k}\ge B_{j+k}∀k∈[0,m−j],Ai+k≥Bj+k匹配原创 2020-07-17 01:17:04 · 328 阅读 · 0 评论 -
51nod 1668 非010串
dp[i]=2*dp[i-1]-dp[i-2]+dp[i-3]由于有减号,所以矩阵快速幂时,可能会产生负数,要处理掉。#includeusing namespace std;const int siz=3;long long mod=1e9+7;struct mtx{ long long a[siz][siz];}unit;mtx multi(mtx m1,mtx m原创 2017-02-10 10:35:22 · 277 阅读 · 0 评论 -
51nod 1296 有限制的排列
原题hdu4055#include using namespace std;const int MAXN=5050;const long long mod=1e9+7;int a[MAXN];long long dp[2][MAXN];//dp[i][j]表示i位置填好后,末尾为j的答案 int main(){ long long n,k,l,x,flag,i,j,ans转载 2017-02-20 15:39:29 · 336 阅读 · 0 评论 -
51nod 1519 拆方块
水题。。。完全不似5级题的风格。。。。#include using namespace std;const int MAXN=100100;int h[MAXN],dp[2][MAXN];int main(){ int n,i,ans; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) scanf("%d",&h[i]);原创 2017-02-26 16:33:49 · 358 阅读 · 0 评论 -
51nod 1572 宝岛地图
预处理每个点,分别能往四个方向各走多少步。#includeusing namespace std;const int MAXN=1010;const int MAXM=100100;char mp[MAXN][MAXN];int dp[4][MAXN][MAXN];int chx[30],chy[30],suc[30];char dir[MAXM];int len[MAXM原创 2017-06-17 20:59:58 · 264 阅读 · 0 评论 -
51nod 1705 七星剑
期望DP转移,正着来。#includeusing namespace std;const int MAXN=110;const double eps=1e-8;const double INF=1e100;double prob[10][MAXN],suc[10],c[MAXN],dp[10][MAXN];int lose[10][MAXN];int main(){ in原创 2017-07-11 10:08:41 · 359 阅读 · 0 评论 -
51nod 1424 零树
书上跑个DP。#includeusing namespace std;const int MAXN=100100;long long v[MAXN],add[MAXN],sub[MAXN];vector vec[MAXN];void dfs(int x,int fa){ for(int i=0;i<vec[x].size();i++) { if(vec[x][i]==f原创 2017-07-14 15:09:15 · 256 阅读 · 0 评论 -
51nod 1580 铺管道
分三种情况讨论:1.直线2.折一次的折线3.折2次的折线有点麻烦的题//#include#include#includeusing namespace std;const int MAXN=2020;char mp[MAXN][MAXN];int dp[4][MAXN][MAXN],cdp[2][MAXN][MAXN];int main(){ long lon原创 2017-06-27 22:34:47 · 267 阅读 · 0 评论 -
51nod 1293 球与切换器
DP//#include#include#includeusing namespace std;const int MAXN=1010;long long dp[MAXN][MAXN][2];int a[MAXN][MAXN];int main(){ long long k,tmp; int n,m,i,j; while(~scanf("%d%d%lld",&m,&n原创 2017-07-19 13:35:25 · 318 阅读 · 0 评论 -
51nod 1610 路径计数
因为是无环图,所以可以用记忆化搜索做。可以根据公约数,将图拆成100个子图。由于有重复,所以再加上容斥。#includeusing namespace std;const long long mod=1e9+7;const int MAXM=50050;long long dp[110];int a[MAXM],b[MAXM],c[MAXM];int mat[110][1原创 2017-07-23 16:23:19 · 359 阅读 · 0 评论 -
牛客OI周赛8-提高组 B 死宅选点
由于我们只要选取总权值最小的点,而当时,我们可以将该路径的权值,等价于进行考虑,对结果没有影响。即长度为m的路径,权值为。很容易得到,条与点距离为的路径,等价于条与点距离为的路径。在处理时,可以采取如此的合并拆分操作。设表示在点的子树中,与点距离为的路径数量。设表示在整棵树中,与点距离为的路径数量。可以通过以下转移式得到:可以通过以下转移式得到:,其中为的父节点...原创 2019-04-18 05:29:40 · 201 阅读 · 0 评论 -
51nod 1378 夹克老爷的愤怒
设dp[x]表示x节点,能够向上控制几个节点。欠控制时,为负。#includeusing namespace std;const int MAXN=100100;int dp[MAXN];vector vec[MAXN];int ans,k;int dfs(int x,int fa){ int mn=1<<30,mx=-(1<<30); for(int i=0;i<vec转载 2017-02-17 13:41:25 · 271 阅读 · 0 评论 -
51nod 1274 最长递增路径
DP题,不过写得有点奇怪。。。将边按边权值排序,dp[x]表示走到x点为止的最长路径。然后不断转移。需要注意的是边权值相等时,应该从边权值更小的地方转移,而非边权值等价的地方转移。每个节点打个 修改时间标记,并记录修改之前的数据,就可以解决这个问题。#includeusing namespace std;const int MAXN=50050;int dp[MAXN],tim[MAX原创 2017-02-08 12:52:41 · 477 阅读 · 0 评论 -
51nod 1603 限高二叉排列树
挺经典的DP。dp[i][j]表示高度为i,节点数为j时的方案总数。#includeusing namespace std;int main(){ long long n,h,i,lef,rig,k,ans; long long dp[40][40]; while(~scanf("%lld%lld",&n,&h)) { memset(dp,0,sizeof(dp));原创 2017-02-07 15:34:59 · 328 阅读 · 1 评论 -
51nod 1455 宝石猎人
很容易想到dp,但是直接dp的话,30000*30000的空间开不下。可以采用跳跃步数和d的偏差量的方法。由于偏差量不超过250,因此第二维可以储存偏差量,而非每次的步数。偏差量不超过250很好证明。若超过了,则必然已经调到30000以外了。#includeusing namespace std;int val[30030],dp[30030][610];int main()原创 2016-11-06 00:23:37 · 333 阅读 · 0 评论 -
51nod 1412 AVL树的种类
#includeusing namespace std;const long long mod=1e9+7;long long dp[20][2020]; int main(){ long long n,i,j,k,ans; memset(dp,0,sizeof(dp)); dp[0][0]=dp[1][1]=1; for(i=2;i<16;i++) { for(j=转载 2016-11-14 20:42:54 · 242 阅读 · 0 评论 -
51nod 1201 整数划分
偷懒写了记忆化,没爆栈真的好神奇。。。因为每次操作最大为2*mod,所以数组开int就够了dp[x][y]=(dfs(x-y,y-1)+dfs(x-y,y))%mod;dp[x][y]表示y个不同的数字之和x的种数。#includeusing namespace std;const int mod=1e9+7;int dp[50050][350];int dfs(int原创 2016-11-30 22:14:03 · 207 阅读 · 0 评论 -
51nod 1052 最大M子段和
设 dp[i][j] 表示前i个元素,选取j个区间,且第i个元素必选的情况下的最大字段和。dp[i][j]=max(dp[i-1][j]+a[i],max(dp[k,j-1]+a[i]));0≤k≤i-1空间压缩一下,前缀也dp一下就好了。#includeusing namespace std;const int MAXN=5050;long long a[MAXN],dp原创 2016-11-30 22:52:54 · 261 阅读 · 0 评论 -
51nod 1055 最长等差数列
dp转移很神奇,枚举中间点。有点像floyd。#includeusing namespace std;const int MAXN=10010;short int dp[MAXN][MAXN];int a[MAXN];int main(){ int n,i,j,k,ans; while(~scanf("%d",&n)) { memset(dp,0,sizeof(dp)原创 2016-12-01 22:39:22 · 296 阅读 · 0 评论 -
51nod 1464 半回文
一开始想到后缀数组,然后发现好难处理对称的。参考了 f_zyj 的代码,发现用字典树做,对称采用了DP优化。这个DP优化好神奇啊。。。。打完后想想,好像后缀数组也能做。。。。#includeusing namespace std;const int MAXN=200200;char s[MAXN];int cnt,n,k,vis[5050];bool dp[5050][5050原创 2016-11-21 01:29:39 · 375 阅读 · 0 评论 -
51nod 1241 特殊的排序
dp求一下最长的等差数列,其余数字向前向后移动,就排好序了。#includeusing namespace std;const int MAXN=50050;int a[MAXN],dp[MAXN];int main(){ int n,i,ans; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) scanf("%d",&a[i原创 2016-12-06 23:20:35 · 243 阅读 · 0 评论 -
51nod 1020 逆序排列
dp+内存压缩+前缀和+离线处理dp[i][j] 表示 n=i,k=j 时的答案。pre[i][j] 表示在 dp[i][j] 的前缀和。转移方程:dp[i][j]=pre[i-1][j]-(j-i>=0?pre[i-1][j-i]:0)#includeusing namespace std;const long long mod=1e9+7;long long d原创 2016-11-24 20:47:42 · 241 阅读 · 0 评论 -
51nod 1383 整数分解为2的幂
#includeusing namespace std;const int MAXN=1000100;const int mod=1e9+7;int dp[MAXN];int main(){ int i,n; dp[0]=1; for(i=1;i<MAXN;i++) { if(i&1) dp[i]=dp[i-1]; else dp[i]=(dp[i-1]原创 2016-12-07 18:42:41 · 230 阅读 · 0 评论 -
1354 选数字
暴力DP水过,不是k的因子的部分剪枝。#includeusing namespace std;const long long mod=1e9+7;const int MAXN=1010;long long a[MAXN];map mp; map ::iterator it;int main(){ long long T,i,n,k,tmp; scanf("%lld",&原创 2016-12-07 21:15:23 · 762 阅读 · 0 评论 -
51nod 1406 与查询
很巧妙的DP转移方式。#includeusing namespace std;const int MAXN=1e6+1;int sum[MAXN];void read(int&a){ char ch;while(!((ch=getchar())>='0')&&(ch<='9')); a=ch-'0';while(((ch=getchar())>='0')&&(ch<转载 2016-12-08 21:43:37 · 265 阅读 · 0 评论 -
51nod 1781 Pinball
昨天看到时,这题还是三级题的。然后各种想不出。大佬说DP+线段树+离散,想了想可以做。然后今天改成了五级题了。。。L[i]表示球从1位置落下,最后从第i个漏斗出去的情况下,的最小费用。R[i]表示球从n位置落下,最后从第i个漏斗出去的情况下,的最小费用。那么答案就是min(L[i]+R[i]-d[i])。动态转移方程:L[i]=min{L[j] | a[i]≤c[j]≤b[i]}转载 2017-02-07 13:29:32 · 392 阅读 · 1 评论 -
51nod 1503 猪和回文
dp[step][x1][x2]代表从起点、终点分别走了step步,从起点走到了(x1,step-x1),从终点走到了(x2,n+m-2-x2-step)时,前后路径对称的总数。注意特判 mz[0][0]!=mz[n-1][m-1] 的情况,我被坑死了。。。。。#include using namespace std;const long long mod=1e9+7;long l原创 2016-11-04 00:54:23 · 303 阅读 · 0 评论