动态规划

动态规划相关题目

匿名 (未验证) 提交于 2019-12-03 00:34:01
一 袋鼠过河 题目描述: 一只袋鼠要从河这边跳到河对岸,河很宽,但是河中间打了很多桩子,每隔一米就有一个,每个桩子上都有一个弹簧,袋鼠跳到弹簧上就可以跳的更远。每个弹簧力量不同,用一个数字代表它的力量,如果弹簧力量为5,就代表袋鼠下一跳最多能够跳5米,如果为0,就会陷进去无法继续跳跃。河流一共N米宽,袋鼠初始位置就在第一个弹簧上面,要跳到最后一个弹簧之后就算过河了,给定每个弹簧的力量,求袋鼠最少需要多少跳能够到达对岸。如果无法到达输出-1 import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int n=sc.nextInt(); int[] num=new int[n]; for(int i=0;i<n;i++) num[i]=sc.nextInt(); int[] jump=new int[n+1]; for(int m=1;m<n+1;m++) jump[m]=10000; jump[0]=1; for(int k=1;k<=n;k++){ //每次 看走到第k个地方的时候,走了多少步 //走的步数与上一步的走法有关 for(int j=k-1;j>=0;j--){ if(num[j]==0)

动态规划――01背包问题

匿名 (未验证) 提交于 2019-12-03 00:34:01
给定 n 种物品和一个容量为 C 的背包,物品 i 的重量是 wi,其价值为 vi 。 问:应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大? 面对每个物品,我们只有选择拿取或者不拿两种选择,不能选择装入某物品的一部分,也不能装入同一物品多次。 解决办法:声明一个 大小为 m[n][c] 的二维数组,m[ i ][ j ] 表示 在面对第 i 件物品,且背包容量为 j 时所能获得的最大价值 ,那么我们可以很容易分析得出 m[i][j] 的计算方法, (1). j < w[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿 m[ i ][ j ] = m[ i-1 ][ j ] (2). j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值。 如果拿取,m[ i ][ j ]=m[ i-1 ][ j-w[ i ] ] + v[ i ]。 这里的m[ i-1 ][ j-w[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。 如果不拿,m[ i ][ j ] = m[ i-1 ][ j ] , 同(1) 究竟是拿还是不拿,自然是比较这两种情况那种价值最大。 #include <iostream> using namespace std ;

聪明的kk(动态规划)

匿名 (未验证) 提交于 2019-12-03 00:34:01
聪明的kk 时间限制: 1000 65535 KB 难度: 3 描述 聪明的“KK” 非洲某国展馆的设计灵感源于富有传奇色彩的沙漠中陡然起伏的沙丘,体现出本国不断变换和绚丽多彩的自然风光与城市风貌。展馆由五部分组成,馆内影院播放名为《一眨眼的瞬间》的宽银幕短片,反映了建国以来人民生活水平和城市居住环境的惊人巨变。 可移动“沙丘”变戏法 的灵感源于其独特而雄伟的自然景观――富于传奇色彩的险峻沙丘。宏伟的结构、可循环的建材,与大自然相得益彰。环绕一周,发现它正是从沙丘那不断变换的形态中汲取灵感的。外形逼真到无论从哪个角度去观察,都能清楚地辨识出沙丘的特征。 它“坡面”高达20米,微风吹来,你是否感觉到沙的流动?用手去触碰,却发现原来是“魔术戏法”。它表面的不锈钢面板呈现出一种富于变幻的色彩,从不同角度观察,呈现不同色泽,由此来模仿流动沙丘的光感。 走进第三展厅有一个超大的屏幕,通过奇妙的特效,让观众犹如亲身来到浩瀚的沙漠。更为奇妙的是,只见一个小动物“KK”正从沙漠区域(矩形)的左上角沿着向右或向下的方向往右下角跑去。KK太聪明了,它居然能在跑的过程中会选择吃掉尽可能多的虫子线路。 你知道它吃掉多少虫子吗? 输入 )表示沙漠是一个N*M的矩形区域 接下来有N行:每行有M个正整数,Xi1 Xi2 ……Xim 表示各位置中的虫子数(单个空格隔开) 假设“KK”只能向右走或向下走。 输出

动态规划之线性动规

匿名 (未验证) 提交于 2019-12-03 00:30:01
动态规划之线性动规 一、动态规划的基本概念 动态规划是一种用途很广的问题求解方法,它本身并不是一个特定的算法,而是一种思想,一种手段。 它的设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法。不像搜索或数值计算那样,具有一个标准的数学表达式和明确清晰的解题方法。动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。因此在学习时,除了要对基本概念和方法正确理解外,必须具体问题具体分析 ,以丰富的想象力去建立模型,用创造性的技巧去求解。我们也可以通过对若干有代表性的问题的动态规划算法进行分析、讨论,逐渐学会并掌握这一设计方法。 几个专业术语: 1.多阶段决策问题: 2.阶段 3.状态 基本思想 基本模型: 二、动态规划的分类 1.最长上升子序列 问题描述: , 它的子序列为S= ,满足{s 1 <s 2 <s 3 < … < s m } 算法分析: 代码实现: #include<stdio.h> int max(int a,int b) {return (a<b)?b:a;} int main() { int a[1010]; int dp[1010]; int n,i,j,ret; ret=1; scanf("%d",&n

动态规划之Word Break详解

匿名 (未验证) 提交于 2019-12-03 00:29:01
之前刷LeetCode。碰到了这道题。 一开始没想到要用动态规划来解。 后来看了一下答案给的代码,又仔细研究了一下,发现确实是动态规划。 中途看了很多其他人的博客解释,都没把动态规划讲清楚。 所以干脆就自己来写一份详解吧。 首先,把题目贴上来 s dict s For example, given s "leetcode" , dict ["leet", "code"] . "leetcode" "leet code" . 简单来说,就是s能不能由dict中存储的单词拼出来。 注意了,这里有陷阱。不能简单的从前往后substr递增的检查是否包含在dict中,否则会有问题。 下面开始介绍怎么用动态规划来讲。 该说的都说了,接下来到实际问题里面去体会。 先贴出官网给出的标准答案 bool wordBreak(string s, unordered_set<string> &dict) { vector<bool> flag(s.length()+1,false); flag[0] = true; for (int i = 1; i < s.length()+1; ++i) { for (int j = i - 1; j >= 0; j--) { if (flag[j] && dict.count(s.substr(j, i-j)) != 0) { flag[i] = true;

动态规划-最长子序列

匿名 (未验证) 提交于 2019-12-03 00:27:02
递归式: c[i-1][j] 还是 c[i][j-1] 。 代码: int Lcs( string &s1, string &s2, int i, int j, int ** &arr) { if (arr == nullptr ) { arr = new int *[s1.length()+ 1 ]; for ( int i = 0 ; i <= s1.length(); i++) { arr[i] = new int [s2.length()+ 1 ]; } for ( int i = 0 ; i <= s1.length(); i++) { arr[i][ 0 ] = 0 ; for ( int j = 0 ; j <= s2.length(); j++) { arr[ 0 ][j] = 0 ; if (i >= 1 && j >= 1 ) { arr[i][j] = - 1 ; } } } } if (i == 0 || j == 0 ) { arr[i][j] = 0 ; return arr[i][j]; } if (arr[i][j] != - 1 ) { return arr[i][j]; } if (s1[i- 1 ] == s2[j- 1 ]){ arr[i][j]= Lcs(s1, s2, i - 1 , j - 1 ,arr) + 1 ; } else {

动态规划经典问题总结

匿名 (未验证) 提交于 2019-12-03 00:25:02
假设有几种硬币,如1、3、5,并且数量无限。请找出能够组成某个数目的找零所使用最少的硬币数。 这是一道经典的动态规划方法,我们可以维护一个一维动态数组dp,其中dp[i]表示钱数为i时的最小硬币数的找零,递推式为:dp[i] = min(dp[i], dp[i - coins[j]] + 1); 其中coins[j]为第j个硬币,而i - coins[j]为钱数i减去其中一个硬币的值,剩余的钱数在dp数组中找到值,然后加1和当前dp数组中的值做比较,取较小的那个更新dp数组。 class Solution { public : int coinChange( vector < int > & coins, int amount) { int Max = amount + 1 ; vector < int > dp(amount + 1 , Max); dp[ 0 ] = 0 ; for ( int i = 1 ; i <= amount; i++) { for ( int j = 0 ; j < coins.size(); j++) { if (coins[j] <= i) { dp[i] = min(dp[i], dp[i - coins[j]] + 1 ); } } } return dp[amount] > amount ? - 1 : dp[amount]; } };

【天梯】序列型动态规划-3027 线段覆盖 2

匿名 (未验证) 提交于 2019-12-03 00:22:01
#include <iostream> #include <algorithm> using namespace std ; struct light { int a ; int b ; int w ; }; light l [ 1001 ]; bool cmp ( light x , light y ) { if ( x . b == y . b ) return ( x . a < y . a ); else return ( x . b < y . b ); } int main () { int n , t ; cin >> n ; int f [ 1001 ]={ 0 }, g [ 1001 ]={ 0 }; for ( int i = 1 ; i <= n ; i ++) { cin >> l [ i ]. a >> l [ i ]. b >> l [ i ]. w ; if ( l [ i ]. a > l [ i ]. b ){ t = l [ i ]. a ; l [ i ]. a = l [ i ]. b ; l [ i ]. b = t ;} } sort ( l + 1 , l + n + 1 , cmp ); for ( int i = 1 ; i <= n ; i ++) { for ( int j = 1 ; j <= n ; j ++) { if (

动态规划-完全背包系列

匿名 (未验证) 提交于 2019-12-03 00:22:01
完全背包与01背包的区别在于,01背包中所有物品要么选要不不选,完全背包是所有物品可以选任意次。完全背包与01背包很相似,可以将完全背包转换成01背包,也可以找到其状态转移方程。 1.完全背包 2.完全背包变形题-最小乘车费用 3.完全背包变形题-货币系统 1.完全背包 问题描述:有n件物品和一个容量为m的背包,每件物品都有无限件可用,第i件物品的体积为w[i],价值是v[i],求解将哪些物品放入背包可使这些物品的价值总和最大并且不超过背包容量。 说明:完全背包问题和01背包问题相似,可以将其改造成01背包问题。 方法一 :改造状态转移方程:f(n,m) = max{k*v[i]+f(i-1,j-k*w[i])},其中k=0….j/w[i] 这样需要使用三层for循环,时间复杂度高,不推荐。 **方法二:**f(n,m) = max{f(n-1,m),f(n,m-w[n])+v[n]} package com.zd.dp.complete; import java.util.ArrayList; /** * 完全背包问题 * 有n个物品和容量为m的背包,每件物品有无限件,求最价值最大 * */ public class Main { public static void main (String[] args){ int n = 4 ; int [] weight = { 2 ,

【难题】动态规划 NOI 162:Post Office――找状态方程有点难 思路详细

匿名 (未验证) 提交于 2019-12-03 00:22:01
题目: 点击打开链接 题目大意:V个村庄,P个邮局,邮局建在村庄上,求一种建法,让V个村庄到最近邮局的距离最小 m[i][j]:表示从i到j只建立一个邮局的路径的最小值 若从第i个村庄到第j个村庄只选取一个作为邮局的话则选择第(i+j)/2个 一开始我没懂,直到自己画了个图,假设把在5建的邮局移到4,则其他村庄的距离变化如图,从4到3不会变化,所以除法向下取整不会有问题。 则状态转移方程:m[i][j]=m[i][j-1]+a[i]-a[(i+j)/2] 怎么理解呢? 1)i+j为偶数,有以下序列,此时在2建邮局 2)i+j为奇数,有以下序列,此时在2建邮局 所以得: dp[i][1]=m[1][i]; dp[i][j]=min{dp[k][j-1]+m[k+1][i]}(1<=k<i) 思路参考了这位博主: 点击打开链接 #include<iostream> #include<algorithm> #include<string.h> using namespace std; int a[301],m[301][301]={0},dp[301][31]={0}; int main() { int V,P,i,j,sum=0,k; cin>>V;cin>>P; for (i=1;i<=V;i++) { cin>>a[i]; sum+=a[i]; } for (i=1;i<=V;i+