动态规划
入门
ddgo
给我高高飞起来啊!(ACM退役,转JAVA后端了)
展开
-
跳跃游戏 (dp + 单调队列) (LC)
题目地址设dp[i] 为 跳到当前这个点的最大值。状态方程为 max{dp[i-k],…,dp[i-1]} + nums[j]. i-k >= 0;表示当前这个点可以由这些点跳过来。因为n和k都很大。故观察第二层,可以维护单调队列,维护区间长度为k的dp[i]的最大值。每次只需要取出最大的dp[i] 去转移.或者用mutilset来维护。代码:单调队列class Solution {public: int maxResult(vector<int>&原创 2020-12-21 20:58:27 · 243 阅读 · 0 评论 -
HDU 1421搬寝室 swustOJ1151搬运工
HDU地址思路,要使得差值方最小,一定是选择连续的两个数。先把数组从小到大排序。构建出它们的差值方数组。当我们选取了一个数,那么这个数左右相邻的两个数都不能被选择。所以题意就转换为。给一个序列(我们处理好的),求在序列中选取不相邻的k个数,使得最大值最小。这样就可以转换为dp了。设转移状态为dp[i][j] 表示前i个中选择j个数的最下值。那么dp[i][j] = min(dp[i-1][j],dp[i-2][j-1] + a[i]) 表示,当前状态由当前这个不选(dp[i-1][j])转移过来,原创 2020-11-21 17:07:40 · 117 阅读 · 0 评论 -
送外卖的小鸽鸽Mannix (dij+状压DP)
离散化坑死人了 !!! 不排序就lower_bound。。。用dijkstra跑出每一个点到其它点的距离,注意一定要加入1号点且,有多的1就不用加入。k = 现在vector 里面的数量跑k遍dijkstra。 得到一个k * k 的图, 现在的目标就是在这个图中,从1开始,经过每一个点且回到原点的最短距离。 哈密顿回路板子。可以参考之前写的哈密顿回路。#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include原创 2020-10-27 18:13:31 · 147 阅读 · 0 评论 -
无聊的开车 (状压DP)
题目地址每个起点与终点组成一个状态节点,然后实现状态转移,注意权值的计算,dis -> 等于上一个点的终点到下一个点的起点+ 下一个点的起点到下一个点的乘2.和哈密顿的那个类似:#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include<bits/stdc++.h>#define int long longusing namespace std;typedef pair<int,int原创 2020-10-27 00:18:27 · 132 阅读 · 0 评论 -
k上升段(DP)
题目地址以1,1为起点设dp[i][j] 为 以i个数全排列中j上升段的个数。特殊的dp[1][1] 为 1转移方程 看上一次某些状态假设上一次的一个状态为 dp[i-1][j]可以把当前的i这个数每次分别插入到每一段的末尾, 即dp[i][j] = j*dp[i-1][j];假设上一次的一个状态为 dp[i-1][j-1]可以把当前的i这个数每次分别插入到除每一段的末尾的地方, 即dp[i][j] = (i-j+1)*dp[i-1][j-1];对于其它状态dp[i-1][j-2]不可能转原创 2020-10-14 21:10:07 · 337 阅读 · 0 评论 -
swust 649: NBA Finals (DP)
题目地址数据好像有些问题。官方的地址有点难找,所以不能完全验证下面正确。法1dp[i][j] 表示 A赢差i次B赢差j次 A赢得概率,输出dp[n][n]故有状态转移方程为 dp[i][j] = dp[i-1][j] * p + dp[i][j-1] * (1-p)A赢i次B赢j次得概率为 A赢i-1次且B赢j次并且这次A赢 + …代码:int n; cin>>n>>p; for(int i=1;i<=n;i++){ dp[i][0] = 0; dp[原创 2020-10-11 18:13:12 · 343 阅读 · 0 评论 -
Independent Task Scheduling
题目地址思路:dp[i][A] 表示第i件物品,花费A机器A的时间且花费B机器dp[i][A]的时间的最小值dp[i][A] = min(dp[i-1][A-a[i]],dp[i-1][A]+b[i]);1:dp[i-1][A-a[i]] 表示第i件物品用于A机器处理;2:dp[i-1][A] + b[i] 表示用于B机器处理,当前A机器还是要处理A的时间 3:最后一个最优的时间为 min{max(A,dp[n][A]),....,...}4: 不需要初始化dp为INF,因为5: 第一维可以原创 2020-10-07 15:20:19 · 134 阅读 · 0 评论 -
哈密顿路径 状压DP
对于某类问题, 求解经过所有点的最短路径(哈密顿路径)或者求经过所有点最短路径后再回到开始的地方(哈密顿回路)例如旅行商问题(TSP)。首先我们假设 每个点与点之间的权值(路的长度)已经求出 记为 w[i][j].(对于这个部分有些时候需要进行处理,自己去把权值求出来)我们把每一个点的状态压缩到应该二进制的位 1代表走这个点,0代表没有走这个点。对于某一个状态,我们可以得到它可以由哪一个状态转移过来。(设有7个点)例如: 当前我们得到了一个状态 1000001 表示第1个点和第7个点走过,而它的原创 2020-10-06 22:40:17 · 656 阅读 · 0 评论 -
Codeforces Round #662 (Div. 2)
A:第一次操作把最外环处理,结下来每次操作会把一个环处理完,并且向里面的一个环处理。可以的出为n/2+1;#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include<bits/stdc++.h>#define int long long#define sc scanf#define pf printfusing namespace std;typedef pair<int,int>原创 2020-08-25 13:43:21 · 131 阅读 · 0 评论 -
Educational Codeforces Round 93 (Rated for Div. 2)A~D
A:a[1] + a[2] > a[n] 最小的两个加起来都比第三边大,则-1.#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include<iostream>#include<algorithm>#include<cstring>#define int long long#define sc scanf#define pf printfusing namespace原创 2020-08-25 00:28:49 · 75 阅读 · 0 评论 -
2020牛客多校第三场 E
给你一个a序列,让你求出对于某个p序列和q序列,pi!=qi 使得它们花费的费用最少。对于p序列的定义,可以知道,下标和值是交换的,即对于 i,j 这两个位置,有pi = j, pj = i,p(pi) = i,p(pj) = i.对于费用的计算,我们知道,只有两个值差不多相同的减去才可能最小。故把a sort一遍,此时构造p,上面对p序列的定义和对费用计算的理解,知道,只需要将p按1~n构造后,再把相邻的交换一下,就可以的到p数组.q数组为了满足次小,故与p构造差不多,只需要将(1 ~ n)序列原创 2020-08-19 17:32:29 · 143 阅读 · 0 评论 -
hdu 6867 Tree
题目地址题意,给一个有向树,判断加一个有向边之后,使得(x,y)对最大,x,y表示x能到达y。思路,对于根节点,它能到达每一个节点(最多),所以我们可以把叶子节点和根节点链接起来形成一个环,就会得到尽可能多的(x,y)。默认将自己也作为子树的一个节点.(后面处理防止(x,x)重复计算)链接后,对于叶子节点,它能够多到达所有的不是它子树的节点,对于叶子节点的父节点,它能多到达所有的不是它子树的结点,…。所以可以用dfs求出 每个节点子树的大小,再dfs求出某条到叶子节点路径的 ∑(n−siz[])原创 2020-08-19 12:10:07 · 152 阅读 · 0 评论 -
最长上升子序列dpO(n^2) 和 O(nlgn)
题目地址描述给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。输入格式第一行包含整数N。第二行包含N个整数,表示完整序列。输出格式输出一个整数,表示最大长度。数据范围1≤N≤1000,−109≤数列中的数≤109输入样例:73 1 2 1 8 5 6输出样例:4法1: 用f[i] 表示 数列中以i为结尾的最长严格单调递增的子序列的最长长度,则有当 a[i] > a[j] {j 为 0~i-1 } 中的一个数时 ,有f[i] = max(f[i],f[j原创 2020-06-25 23:23:11 · 159 阅读 · 0 评论 -
uva 1025
以dp[i][j] 表示 第i分到第j站最长的等待时间,INF表示在第i分的时候到不到j站。有3个决策。1:当前等待一分钟。2: 乘坐往右的车(如果有)3: 乘坐往左的车(如果有)主要过程代码与紫书类似,不过我是从i=1开始枚举的。主要就是has_train的处理。车的出发时间加上站与站之间的时间就可以算出第i分到第j站void check_train(){ for(int i=1;i<=m1;i++){ int res = t1[i]; for(int j=0;j<n原创 2020-07-30 20:57:25 · 148 阅读 · 0 评论 -
uva 437
题意和思路紫书上都有,(DAG上的最长路)关键是建立图模型。邻接链表:#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include<bits/stdc++.h>#define int long longusing namespace std;typedef pair<int,int> pii;typedef long long ll; const int INF = 0x3f3f3f3原创 2020-07-31 10:40:34 · 109 阅读 · 0 评论 -
uva 1347
把行走路线看为两个人走不同点形成的路线到终点。考虑状态的转移,令dp(i,j) 表示1~max(i,j)全部走过,且第一个人在i位置,第二个人在j位置。至少还需要dp[i][j] 的距离到终点分析状态转移当前状态可以转换为第一个同学往后面没有走过的走,或者第二个同学往后面没有走过的走,可以的到dp(i,j) -> dp(i+1,j) 或 dp(i,i+1). 规定i > j 因为有dp(i,j)等于dp(j,i) 。故转换方程为 dp(i+1,j) 或dp(i+1,i).转移具体原创 2020-07-31 14:43:21 · 96 阅读 · 0 评论 -
uva 116
单递推的话很简单们,可以正推和逆推,为了求出字典序最小,所以逆推比较好算,用ne存第i第j列 接下来走的是几行,找到起点就可以输出路径了。代码#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#include<bits/stdc++.h>#define int long longusing namespace std;typedef pair<int,int> pii;typedef long原创 2020-07-31 18:34:20 · 125 阅读 · 0 评论 -
洛 p5662 纪念品(完全背包)
卖了这个物品的当天,当天也可以买。 这样只需判断如果前一天比今天的价格低,前一天就买来赚差价。 存下满足的物品(也可以不存,后面直接特判也一样)vector<int> ve;for(int j=1;j<=m;j++) if(w[i1][j]-w[i1-1][j] > 0) ve.push_back(j);重点是,当有多个物品满足这个条件时,应该怎么做。这里直接翻译一下。多个物品,且每个物品在金钱允许范围内任意选,求任意选的物品的组合赚的差价最大值。这就是完全背包。原创 2020-07-11 15:23:56 · 223 阅读 · 0 评论