动态规划

动态规划例子:niconiconconiconi,,,,,,

梦想的初衷 提交于 2020-02-05 17:26:27
题目 : 加粗样式 链接 来源:牛客网 知识点:动态规划菜鸡,,,, 我真不好解释 动态规划知识点运用链接***加粗样式*** nico平时最喜欢说的口头禅是niconiconi~。 有一天nico在逛著名弹幕网站"niconico"的时候惊异的发现,n站上居然有很多她的鬼畜视频。其中有一个名为 《让nico为你洗脑》的视频吸引了她的注意。 她点进去一看,就被洗脑了:“niconicoh0niconico*^vvniconicoG(vniconiconiconiconiconicoG(vniconico…” 弹幕中刚开始有很多“nico 1 nico 2”等计数菌,但到后面基本上都是“计数菌阵亡”的弹幕了。 nico也想当一回计数菌。她认为:“nico” 计 分,“niconi” 计 分,“niconiconi” 计 分。 她拿到了一个长度为 的字符串,请帮她算出最大计数分数。 注:已被计数过的字符不能重复计数!如"niconico"要么当作"nico"+“nico"计 分,要么当作"niconi”+"co"计 分。 输入描述: 第一行四个正整数 。 第二行是一个长度为 的字符串。 输出描述: 一个整数,代表最大的计数分数。 示例1 输入 19 1 2 5 niconiconiconiconi~ 19 1 2 5 niconiconiconiconi~ 输出 7 7 说明

【剑指offer】斐波那契数列

落爺英雄遲暮 提交于 2020-02-04 13:14:33
题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39 下面首先会简单介绍递归算法,然后给出递归算法的解法代码,以及使用非递归算法的解决代码,最后是简单使用动态规划的方法解决。 递归算法 斐波那契数列是典型的递归代表。递归算法的核心在于两点: 结束递归的边界条件 递归公式 递归公式简单理解起来,就是类似于我们高中数学里可以用式子表达的数列,类似于初中学的找前后的规律,只是把这个规律公式化了。 递归算法的两个核心要点,对应到代码算法的实现,也就是以下 3 步: 找整个递归的终止条件:递归应该在什么时候结束? 找返回值:应该给上一级返回什么信息? 本级递归应该做什么:这一级递归中,要完成什么任务? 举个例子:假设有个数列 1 3 5 7 9 11 … 找到第n项的值。在这个数列中,开始的一项是 1,是无规律可循的一项,这一项到数列的尽头了,是 “结束” 项;此后,每一项都是在其前一项的基础上加 2,得到的。因此可以写为: 边界条件:f(1) = 1 递归公式:f(n) = f(n-1)+2 找到上述的两个要点,就可以实现递归算法。 解题思路 这一道题中,要求返回斐波那契数列的第 n 项,从 0 开始。 斐波那契数列:0 1 1 2 3 5 8 13 … 可以知道其边界条件和递归公式分别为: fibonacci(1) =

整数拆分问题的动态规划解法

不羁的心 提交于 2020-02-04 07:45:13
给定一个自然数,分成k部分,A1,A2..的数的和,要求A1<=A2...求有多少种? 原理:整数n拆分成最多不超过 m个数 的和的拆分数,和n 拆分成最大 不超过m 的拆分数相等。 根据这个原理,原问题就转化成了求最大拆分为k的拆分个数与最大拆分为k-1的拆分个数的和 (或原问题就转化成了求正好拆分为k个数的拆分方案数与最大拆分为k-1的拆分个数的和) f(n,k)=f(n,k-1)+f(n-k,k) 实际上也可以看成完全背包问题: 物品有k件: 物品1:1 物品2:1,1 物品3:1,1,1 ... 物品k:1,1,..,1(k个) 为什么可以这么看呢:因为要求A1<=A2,虽然是升序,反放来也可以看成降序,所以。。。 f[i,j]=f[i-1,j]+f[i,j-cost[i]] 而其实cost[i]=i 所以:f[i,j]=f[i-1,j]+f[i,j-i] 来源: https://www.cnblogs.com/nbalive2001/p/4079332.html

蓝桥杯:K好数 动态规划解法

こ雲淡風輕ζ 提交于 2020-02-04 04:34:47
蓝桥杯:K好数 动态规划解法 问题描述 如果一个自然数N的K进制表示中任意的相邻的两位都不是相邻的数字,那么我们就说这个数是K好数。求L位K进制数中K好数的数目。例如K = 4,L = 2的时候,所有K好数为11、13、20、22、30、31、33 共7个。由于这个数目很大,请你输出它对1000000007取模后的值。 输入格式 输入包含两个正整数,K和L。 输出格式 输出一个整数,表示答案对1000000007取模后的值。 样例输入 4 2 样例输出 7 数据规模与约定 对于30%的数据,K L <= 10 6 ; 对于50%的数据,K <= 16, L <= 10; 对于100%的数据,1 <= K,L <= 100。 思路 因为数字不能相邻,那么第 i 位的填写,取决于第 i-1 位的数字 若第 i-1 位数字为 0 或者 k-1,第 i 位有 k-1 种选择 例:四进制,可选0,1,2,3 现有长度位2的数字:30,现在填第三位,可以选0,2,3 现有长度位2的数字:13,现在填第三位,可以选0,1,3 若第 i-1 位数字为 1~k-2,第 i 位有 k-2 种选择 例:四进制,可选0,1,2,3 现有长度位2的数字:31,现在填第三位,可以选1,3 现有长度位2的数字:12,现在填第三位,可以选0,2 那么长度为len,结尾数字为 x 的K好数的数目,就是 所有

动态规划-Cherry Pickup

不羁岁月 提交于 2020-02-03 18:20:33
2020-02-03 17:46:04 问题描述 : 问题求解 : 非常好的题目,和two thumb其实非常类似,但是还是有个一点区别,就是本题要求最后要到达(n - 1, n - 1),只有到达了(n - 1, n - 1)才算是有效解,two thumb是一定会有解的,所以不用加特别判断。 也是一种路径规划类的题目,难点依然是状态的表示,我们这里使用的p1,p2的坐标位置作为状态。 另外,还需要注意的是在超界的时候,我们需要返回的是Integer.MIN_VALUE,这样就可以规避掉一些中间节点到不了终点的情况。 int[][][] dp = new int[51][51][51]; public int cherryPickup(int[][] grid) { int n = grid.length; for (int i = 0; i <= 50; i++) { for (int j = 0; j <= 50; j++) { Arrays.fill(dp[i][j], -1); } } int res = dfs(grid, 0, 0, 0); return dp[n - 1][n - 1][n - 1] == -1 ? 0 : res; } private int dfs(int[][] grid, int x1, int y1, int x2) { int n =

地下城游戏--逆动态规划--LeetCode.174

浪尽此生 提交于 2020-02-03 16:36:40
题目链接 https://leetcode-cn.com/problems/dungeon-game/ 解题思路: 状态转移方程: dp[i][j]=max(1,min(dp[i+1][j],dp[i][j+1])-dungeon[i][j]). 代码: class Solution { public: int calculateMinimumHP(vector<vector<int>>& dungeon) { int row=dungeon.size(); if(row==0)return 0; int col=dungeon[0].size(); vector<vector<int>>dp(row,vector<int>(col)); dp[row-1][col-1]=max(1,1-dungeon[row-1][col-1]); for(int i=row-2;i>=0;i--){ dp[i][col-1]=max(1,dp[i+1][col-1]-dungeon[i][col-1]); } for(int i=col-2;i>=0;i--){ dp[row-1][i]=max(1,dp[row-1][i+1]-dungeon[row-1][i]); } for(int i=row-2;i>=0;i--){ for(int j=col-2;j>=0;j--){ dp[i][j

牛客刷题记录(四)

五迷三道 提交于 2020-02-03 08:30:36
【快手】最少数量货物装箱问题 题目地址 知识点:动态规划 解题思路: 1.动态规划 状态转移方程: dp[i] = min(dp[i-3], dp[i-5], dp[i-7]) + 1 我们初始化1 - 7的dp数组,可以装满的重量状态初始化为最小数量,如果不能装满就初始化为100001,标志无法走通。 如果总重量N是(3, 5, 7)是其中至少任意一个数的倍数,那么此路径可以走通,是一个小于100001的值,如果大于等于100001,那么无法装满 2.(3, 5, 7)的最小公倍数是105,只要可以整除105,那么就可以装满,105最少装满的数量是15。最终余数小于105,可以直接穷举法求解,复杂度也不会很高。 3. 这个很难想到,是评论区大哥的思路: 对7取余,对余数进行讨论即可 余数为1,3,5,则可以装满,1可以视为1+7=3+5,依旧是之前的count+1 余数为2,4,6,也可以装满,2可以视为2+7=3+3+3,4可以视为4+7=5+3+3,6=3+3是之前的count+2 # include <bits/stdc++.h> using namespace std ; # define MAX 10001 int main ( ) { int x ; cin >> x ; vector < int > dp ( x + 1 , MAX ) ; dp [ 3 ] = 1

算法之动态规划(思想)

生来就可爱ヽ(ⅴ<●) 提交于 2020-02-03 02:52:41
写在前面的话: 动态规划是一种问题求解方法,它本身并不是一个特定的算法,而是一种思想、一种手段。 状态 、 状态转移方程 、最优子结构(全局最优解包含局部最优) 三角形上的动态规划 (d为路径距离,a为单个距离) 状态方程: d(I,j) = a(I,j) + max(d(I+1,j),d(I+1,j+1)) 得出 递归代码 (重复计算): int solve ( int i , int j ) { return a [ i ] [ j ] + ( i == n ? 0 : max ( solve ( i , j + 1 ) , solve ( i + 1 , j + 1 ) ) ) ; } 递推计算 (从下往上): int i , j ; for ( j = 1 ; j <= n ; j ++ ) { // 最后一行赋值 d [ n ] [ j ] = a [ n ] [ j ] ; } for ( i = n - 1 ; i >= 1 ; i -- ) { for ( j = 1 ; j <= i - 1 ; j ++ ) { d [ i ] [ j ] = a [ i ] [ j ] + max ( b [ i + 1 ] [ j ] , b [ i + 1 ] [ j + 1 ] ) ; } } return d [ 1 ] [ 1 ] ; // 递推到最上面,一定是最优解

( 动态规划专题 )【 树形dp 】

≯℡__Kan透↙ 提交于 2020-02-03 02:05:33
( 动态规划专题 )【 树形dp 】 树形DP是一种DP的思想,只不过普通dp是在数组上进行的,而树形dp是在树上进行的。 直接看例题:P2015 二叉苹果树 题目链接: https://www.luogu.com.cn/problem/P2015 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N, 树根编号一定是1 。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 输入格式 第1行2个数,N和Q(1<=Q<= N,1<N<=100)。 N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。 每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过30000个。 输出格式 一个数,最多能留住的苹果的数量。 输入输出样例 输入 #1 5 2 1 3 1 1 4 10 2 3 20 3 5 20 输出 #1 21 思路: 很明显,这是一个树状结构,我们可以从这点出发来考虑。这道题明确给出了根的位置,也就确定了父子节点的关系,我们会发现,对于每个父节点的状态

动态规划学习之旅

让人想犯罪 __ 提交于 2020-02-02 21:48:16
什么是动态规划 动态规划也称DP是一种用来解决一类最优化问题的算法思想,它将一个复杂的问题分解成若干子问题,动态规划将每个子问题的解记录下来,最后综合子问题的最优解得到该问题的最优解。同时需要注意的是如果一个问题被分解成了若干子问题并且这些子问题会重复出现,那么称这些问题为重叠子问题(overlapping subproblems) 一个问题必须拥有重叠子问题,才能使用动态规划去解决。 另外还有最优子结构(optimal substructure),最优子结构是指一个问题的最优解可以由它子问题的最优解得到,所以最优子结构保证了动态规划的最优解的可能性, 因此一个问题必须拥有最优子结构才可以使用动态规划去解决。 2.经典问题 数塔问题 数塔问题即计算从最上边的数字到底层数字所有数字相加后的最大值是多少。 # include <iostream> # include <algorithm> # include <cmath> # define maxn 1005 using namespace std ; int f [ maxn ] [ maxn ] , dp [ maxn ] [ maxn ] ; //f数组表示第i行第j列数字是多少,dp数组表示从第i行第j列到最 //底层所有路径中能得到的最大值 int main ( ) { int n ; cin >> n ; for (