动态规划

算法 - 动态规划

天大地大妈咪最大 提交于 2019-12-01 08:58:06
定义 无后效性: 不是因为题目本身无后效性,而是我们通过代码,避开了有后效性的情况。 基本步骤 问题共性 离散问题:简单理解就是“整数是离散的,小数是连续的”。 来源: https://www.cnblogs.com/frankcui/p/11674594.html

[动态规划]最少硬币问题

心已入冬 提交于 2019-12-01 08:24:18
最少硬币问题 http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/contestproblem/cid/3016/pid/1725 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱。可以使用的各种面值的硬币个数存于数组Coins[1:n]中。 对任意钱数0≤m≤20001,设计一个用最少硬币找钱m的方法。 对于给定的1≤n≤10,硬币面值数组T和可以使用的各种面值的硬币个数数组Coins,以及钱数m,0≤m≤20001,计算找钱m的最少硬币数。 Input 输入数据第一行中只有1个整数给出n的值,第2行起每行2个数,分别是T[j]和Coins[j]。最后1行是要找的钱数m。 Output 输出数据只有一个整数,表示计算出的最少硬币数。问题无解时输出-1。 Sample Input 3 1 3 2 3 5 3 18 Sample Output 5 Hint Source 算法思路: 这题采用"动态规划"算法,将大问题转换为小问题,且一步步记录上一步的结果。 我们依旧使用一维数组来存储计算结果,可以参考之前的一个"背包问题"的算法解读:https://www

数组标签结束,下一个标签,动态规划

两盒软妹~` 提交于 2019-12-01 08:00:59
想着每个标签做20道题进行练习 以上是数组标签前20道题中完成的题目,还有三个没完成,54是没地方写程序,前两个是自己运行可以但是上传就不对了。 无论如何也算是完成了一小步,接下来进行下一个目标,动态规划!!!! 动态规划(英语:Dynamic programming,简称 DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。 动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。 通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。 链接:https://leetcode-cn.com/tag/dynamic-programming/ 来源:力扣(LeetCode) ——2019.10.14 来源:

知识点

吃可爱长大的小学妹 提交于 2019-12-01 07:08:42
一、 C++的标准模版库的应用. (poj3096,poj3007) 较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706) 差分约束系统的建立和求解. (poj1201,poj2983) 最小费用最大流(poj2516,poj2516,poj2195) 双连通分量(poj2942) 强连通分支及其缩点.(poj2186) 图的割边和割点(poj3352) 最小割模型、网络流规约(poj3308, ) 线段树. (poj2528,poj2828,poj2777,poj2886,poj2750) 静态二叉检索树. (poj2482,poj2352) 树状树组(poj1195,poj3321) RMQ. (poj3264,poj3368) 并查集的高级应用. (poj1703,2492) KMP算法. (poj1961,poj2406) 最优化剪枝和可行性剪枝 搜索的技巧和优化 (poj3411,poj1724) 记忆化搜索(poj3373,poj1691) 较为复杂的动态规划(如动态规划解特别的施行商问题等)(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034) 记录状态的动态规划. (POJ3254,poj2411,poj1185) 树型动态规划(poj2057

动态规划训练之十一

时光总嘲笑我的痴心妄想 提交于 2019-12-01 04:56:35
https://www.luogu.org/problem/P5196 开始那道题会觉得 计数很棘手 ,思考一番 这个背包dp式子很好得出 if(dp[j]) dp[j+len[i]]+=dp[j]; 但是这是 没有最后一个单词的前提下才行 那怎么办? (不会就dp) --->>很有用的 f[col[i]]+=dp[k-col[i]]; 表示押韵 col 的最后一个放置的方案数 有 x 个压 Y韵 的方案数就为 ksm(f[y],x) ( 快速幂 ) 最后将不同的押韵方案数 累加起来 就好 code: #include<cstdio> #include<iostream> #include<algorithm> #define N 5005 using namespace std; typedef long long LL; int n,m,k; LL s[N],c[N]; LL f[N],g[N]; LL nd[30]; const LL mod=1000000007; LL ksm(LL b,LL k) { if(k==0) return 1; if(k==1) return b%mod; LL q=ksm(b,k>>1); if(k&1) return q*q%mod*b%mod; else return q*q%mod; } bool cmp(LL x,LL y) {

动态规划训练之十

柔情痞子 提交于 2019-12-01 01:51:16
https://www.luogu.org/problem/P3120 首先 ON^4 的dp很容易想到(数据加强过,所以这个过不了) code : #include<bits/stdc++.h> using namespace std; int r,c,k; //行,列,数值限定 int a[751][751]; long long f[751][751]={0}; //f[i][j]:左上f[i][j]严格左上方所有点的路径总数之和 int main() { scanf("%d%d%d",&r,&c,&k); for(int i=0;i<r;i++) for(int j=0;j<c;j++) scanf("%d",&a[i][j]); f[0][0]=1; for(int i=0;i<r;i++) for(int j=0;j<c;j++) //要计算的点 for(int p=0;p<i;p++) for(int q=0;q<j;q++) //左上方的点 if(a[i][j]!=a[p][q])//审题:要求数值不同 f[i][j]=(f[i][j]+f[p][q])%1000000007; //勿忘mod 1000000007 cout<<f[r-1][c-1]<<endl; return 0; } 加强的数据完美卡**到N^2*logN** 首先如果没有 两点的val值不同

最大连续子序列

为君一笑 提交于 2019-11-30 22:28:30
1. 简介 动态规划(dynamic programming)是运筹学的一个分支,是求解决策过程(decision process)最优化的数学方法。20世纪50年代初美国数学家R.E.Bellman等人在研究多阶段决策过程(multistep decision process)的优化问题时,提出了著名的最优化原理(principle of optimality),把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法——动态规划。--百度百科 2. 解决的问题 最优性原理是动态规划的基础。任何一个问题,如果失去了这个最优性原理的支持,就不可能用动态规划设计求解。 动态规划是解决最优解的问题,需要满足两个条件。 问题中的状态满足最优性原理。 问题中的状态必须满足无后效性。 所谓无后效性是指:“下一时刻的状态只与当前状态有关,而和当前状态之前的状态无关,当前状态是对以往决策的总结”。 3. 动态规划的关键 - 递归方程 + 边界条件 4. 示例 # 最大连续子序列 nums = [1, 2, -3, -6, 4, 5, 7] def maxsum(nums): if len(nums) == 1: return nums[0] dp = res = nums[0] for i in range(1, len(nums)): dp =

动态规划训练之九

时光总嘲笑我的痴心妄想 提交于 2019-11-30 21:18:04
首先能够想到是 状压dp模板 取 dp[state,i,j] 表示state状态下倒数第二个岛为i,最后一个岛为j时的最优解, num[state,i,j] 为相应的路径数目,其中 state 的二进制表示的i位为1表示岛i被访问过,反之为0。 则显然当有 边(i,j) 存在时,有如下初值可赋: **dp[(1<<i)+(1<<j),i,j]=val[i]+val[j]+val[i]*val[j],num[(1<<i)+(1<<j),i,j]=1。 如果状态 (state,i,j) 可达,检查岛 k ,如果此时 k 没有被访问过并且有边 (j,k) 存在,则做如下操作: 1) 设 tmp 为下一步访问岛k时获得的总利益, r=state|(1<<k) 。 2) 如果 tmp>dp[r,j,k] ,表示此时可以更新到更优解,则更新: dp[i,j,k]=tmp;** num[r,j,k]=num[state,i,j]。 3) 如果 tmp==dp[r,j,k] ,表示此时可以获得达到局部最优解的更多方式,则更新: num[r,j,k]+=num[state,i,j]。 类似于 最短路计数 最后检查所有的状态 ((1<<n)-1,i,j) ,叠加可以得到 最优解的 道路数。 需要注意的是,题目约定一条路径的 两种行走方式算作一种,所以最终结果要除2 。 code(写的很清晰,很明了

[SOJ638] 小 p 与染色【动态规划】【生成函数】

爱⌒轻易说出口 提交于 2019-11-30 21:09:49
娃娃机毒瘤qwq 题意简述:对每个 \(m\in[1, r]\) ,求所有 \(n\) 个点的无向图,染成 \(m\) 种颜色,满足任意边两端节点颜色不同的方案数,对 \(998244353\) 取模。 \(n\leq 8000, r\leq 10^6\) 。 先对节点染色,再考虑连边情况。由此可以得到一个比较显然的dp:设 \(f_{i, j}\) 为实际使用了 \(i\) 种颜色(即每种颜色至少染了一个点),染 \(j\) 个点的方案数,转移时枚举新增的点数 \(k\) ,则: \[f_{i, j}=\sum_{k=1}^{j} f_{i-1, j - k}\cdot \binom{n-j+k}{k} \cdot 2^{(j-k)\cdot k}\] 即,从未染色的 \(n-j+k\) 个点中选择本次新染色的 \(k\) 个点,则这 \(k\) 个点与原来的 \(j-k\) 个点之间的边均可以选择连或不连。 设 \(g_i=f_{i, n}\) ,则 \(m\) 种颜色(有些颜色可以不用)染色的方案数为 \(ans_m=\sum_{i=1}^{m} g_i\cdot \binom{m}{i}\) 。 以上是一个 \(O(n^3+nr)\) 的暴力做法,可以获得 \(60\) 分。 考虑一个长度为 \(m\) 的颜色序列 \(t\) ,满足 \(\sum_{i=1}^m t_i

动态规划训练之八

馋奶兔 提交于 2019-11-30 21:02:07
哎,题型真的变化无穷啊 先考虑如果 每个点只能走一次 ,那么这就是 个典型的状压dp的裸题 , 但这时候每个点可以 最多走两次 ,怎么办? 当每个点只能走两次的时候, 我们用二进制的的0表示该点没有被选到,1表示该点被选到 这时候我们就可以用 三进制 的2表示该点被经过了两次 code(写的很清晰,就是顶格写了,不是很好看): #include <iostream> #include <string> #include <cmath> #include <cstdio> #include <cstring> #include <cstdlib> #include <ctime> #include <queue> #include <stack> #include <list> #include <algorithm> using namespace std; int pat[12] = {0,1,3,9,27,81,243,729,2187,6561,19683,59049}; int n,m; int edge[11][11]; int idx[59049][11] = {0}; int dp[59049][11]; void initidx() { for(int i = 0 ; i < 59049 ; ++i) { int temp = i ; for(int j = 1 ;