动态规划算法

国家集训队论文分类整理

蹲街弑〆低调 提交于 2020-03-02 11:39:00
国家集训队曾经发表过的论文总结 国家集训队1999论文集 陈宏:《数据结构的选择与算法效率——从IOI98试题PICTURE谈起》 来煜坤:《把握本质,灵活运用——动态规划的深入探讨》 齐鑫:《搜索方法中的剪枝优化》 邵铮:《数学模型的建立、比较和应用》 石润婷:《隐蔽化、多维化、开放化——论当今信息学竞赛中数学建模的灵活性》 杨帆:《准确性、全面性、美观性——测试数据设计中的三要素》 周咏基:《论随机化算法的原理与设计》 国家集训队2000论文集 陈彧:《信息学竞赛中的思维方法》 方奇:《动态规划》 高寒蕊:《递推关系的建立及在信息学竞赛中的应用》 郭一:《数学模型及其在信息学竞赛中的应用》 江鹏:《探索构造法解题模式》 李刚:《动态规划的深入讨论》 龙翀:《解决空间规模问题的几种常用的存储结构》 骆骥:《数学模型的建立和选择》 施遥:《人工智能在围棋程序中的应用》 肖洲:《数据结构的在程序设计中的应用》 谢婧:《规模化问题的解题策略》 徐串:《论程序的调试技巧》 徐静:《图论模型的建立与转化》 杨江明:《论数学策略在信息学问题中的应用》 杨培:《非最优化算法初探》 张辰:《动态规划的特点及其应用》 张力:《类比思想在解题中的应用》 张一飞:《冗繁削尽留清瘦——浅谈信息的充分利用》 国家集训队2001论文集 符文杰:《Pólya原理及其应用》 高寒蕊:

动态规划之Fib数列类问题应用

删除回忆录丶 提交于 2020-02-28 11:36:54
一,问题描述 有个小孩上楼梯,共有N阶楼梯, 小孩一次可以上1阶,2阶或者3阶 。走到N阶楼梯,一共有多少种走法? 二,问题分析 DP之自顶向下分析方式: 爬到第N阶楼梯,一共只有三种情况( 全划分,加法原理 ), 从第N-1阶爬1阶到第N阶;从第N-2阶爬2阶到第N阶;从第N-3爬3阶到第N阶 。 故:way(N)=way(N-1)+way(N-2)+way(N-3) 这与求Fib数列非常相似,当然,其他类似的问题也可以这样求解。 初始条件: way(1)=1 way(2)=2 way(3)=4 这里解释一下way(3)=4。爬到第3层一共有4种方式:每次爬一层,1+1+1=3;先爬一层,再爬二层,1+2=3;先爬二层,再爬一层,2+1=3;一次性爬三层。 三,代码实现 public class WaysOfLadder { public static int ways(int n){ if(n <= 0) throw new IllegalArgumentException(); return waysLadder(n); } //递归算法爬上第n阶楼梯一共需要多少种方式 private static int waysLadder(int n){ assert n > 0; //base condition if(n == 1) return 1; if(n == 2)

干货:图解算法——动态规划系列

霸气de小男生 提交于 2020-02-25 19:47:12
小浩:宜信科技中心攻城狮一枚,热爱算法,热爱学习,不拘泥于枯燥编程代码,更喜欢用轻松方式把问题简单阐述,希望喜欢的小伙伴可以多多关注! 动态规划系列一:爬楼梯 1.1 概念讲解 讲解动态规划的资料很多,官方的定义是指把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解。概念中的各阶段之间的关系,其实指的就是状态转移方程。很多人觉得DP难(下文统称动态规划为DP),根本原因是因为DP区别于一些固定形式的算法(比如DFS、二分法、KMP),没有实际的步骤规定第一步第二步来做什么,所以准确的说,DP其实是一种解决问题的思想。 这种思想的本质是:一个规模比较大的问题(可以用两三个参数表示的问题),可以通过若干规模较小的问题的结果来得到的(通常会寻求到一些特殊的计算逻辑,如求最值等) 所以我们一般看到的状态转移方程,基本都是这样: opt :指代特殊的计算逻辑,通常为max or min。 i,j,k 都是在定义DP方程中用到的参数。 dp[i] = opt(dp[i-1])+1 dp[i][j] = w(i,j,k) + opt(dp[i-1][k]) dp[i][j] = opt(dp[i-1][j] + xi, dp[i][j-1] + yj, ...) 每一个状态转移方程,多少都有一些细微的差别。这个其实很容易理解,世间的关系多了去了,不可能抽象出完全可以套用的公式

POJ 1141 Brackets Sequence 动态规划

时光总嘲笑我的痴心妄想 提交于 2020-02-19 04:01:07
在刘汝佳黑书上有详细的解析,自己明天这两种算法自己实现一下,作为对动态规划的深入理解学习 先转一个题解http://blog.163.com/leyni@126/blog/static/16223010220103155534476/?fromdm&fromSearch&isFromSearchEngine=yes 问题:括号匹配问题。给出一个由括号组成字符串,加最少的括号使之匹配。 思路: 设f[i][j]为从i到j这段字串达到匹配所需最少括号数。 初始状态:f[i][i] = 1; 状态转移: f[i][j] = min{f[i + 1][j - 1 | s[i]与s[j]匹配],f[i + 1][j] | s[i]为左括号,f[i][j - 1] | s[i]为右括号,min{f[i][k]+f[k][j]}} #include <iostream> #include <stdlib.h> #include <string.h> using namespace std; const int MAX = 102; char s[MAX]; int f[MAX][MAX], path[MAX][MAX], n; void print(int l, int r){ if (l > r) return; if (l == r){ if (s[l] == '(' || s[l] ==

A - Max Sum Plus Plus(动态规划)本人新手菜鸟勿进,欢迎大神指点✌✌✌

╄→尐↘猪︶ㄣ 提交于 2020-02-16 11:53:20
A - Max Sum Plus Plus 进入正文: Now I think you have got an AC in Ignatius.L’s “Max Sum” problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem. Given a consecutive number sequence S 1, S 2, S 3, S 4 … S x, … S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + … + S j (1 ≤ i ≤ j ≤ n). Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + … + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not

【转】acm学习方法

混江龙づ霸主 提交于 2020-02-16 11:35:11
建议 做到50行以内的程序不用调试、100行以内的二分钟内调试成功. acm主要是考算法的,主要时间是花在思考算法上,不是花在写程序与debug上。 算法集锦 https://www.cnblogs.com/ngyifeng/p/3718601.html 书籍推荐 入门三本: 《数据结构与算法》(傅清祥,王晓东编著,我所见过的最好的算法教材) 程序设计导引及在线实践 作者: 李文新 ACM程序设计培训教程 吴昊 基础提高: 算法设计与分析 这是国内牛人王晓东的大作,非常不错的算法书 算法设计与试验题解 王晓东 计算几何-算法设计与分析 周培德 组合数学 第三版 冯舜玺 译 算法艺术与信息学竞赛 刘汝佳的杰作,引导着信息学竞赛的发展 如果算法导论是九阳神功,那这本无疑就是九阴真经。本书是专为参加一些诸如ACM之类程序设计比赛的同学而写的,江湖人称“黑书”。里面讲的都是一些在编程比赛中常用的算法、数据结构,以及一些数论和计算几何等。我虽然并不搞竞赛,但也从此书中受益颇多。 国际信息学奥林匹克竞赛指导— — 实用算法的分析与程序设计  吴文虎 王建德 Introduction to Algorithm 科曼著 传说中的宝典 算法导论(原书第3版) Algorithms 算法概论 短小精悍,别据一格,准经典之作。一个坏消息: 同算法导论,该书没有习题答案。好消息:习题很经典,难度也适中

CF1015F Bracket Substring(动态规划)

天涯浪子 提交于 2020-02-11 15:46:18
CF1015F Bracket Substring 这题一眼 GT考试 题意: 求有多少种合法的括号序列要求字符串S是其字串 数据范围大概是一个 \(\Theta(n^3)\) 的算法 从前往后填括号, 设 \(F[i][j][k]\) 表示填到第 \(i\) 位, "和"为 \(j\) , 匹配了 \(S k\) 位, 其中和的定义为将左括号看做1, 右括号看作-1, 一个合法的括号序列的前缀和总大于等于零且本身的和为零(一个左括号一定匹配一个右括号) \(dp\) 时只需枚举下一位填 \('('\) 或 \(')'\) 即可, 但要注意的是匹配 \(S\) 串时从第 \(k\) 位不匹配不是直接重新从0开始匹配而是求出它的 \(kmp\) 数组, 找到上一个 \(border\) , 可以参考代码 #pragma GCC optimize(2) #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define ll long long using namespace std; template <typename T> void read(T &x) { x = 0; bool f = 0; char c = getchar(); for (;!isdigit(c);c

动态规划算法实例的一些实现

喜欢而已 提交于 2020-02-11 03:44:09
/*This is the template of *.cpp files */ #include<iostream> #include<vector> using namespace std; int cut_rod(int *p,int n ){//暴力法求最优切割 if(n == 0) return 0; int q = -1; for(int i = 1;i<=n;++i){ q = q>p[i] + cut_rod(p,n-i)?q:p[i] + cut_rod(p,n-i); } return q; } int end_cut_rod(int *p,int n){//自底向上动态规划算法求最优切割方法的价值 以及切割方案 int *r = new int[n+1]; int *s = new int[n+1]; for(int m = 0;m<=n;++m){ r[m] = 0; s[m] = 0; } for(int i = 1;i <= n;++i){ for(int j = 0;j < i;++j){ int temp = r[j] + p[i-j]; if(r[i] < temp){ r[i] = temp; s[i] = i - j; } } } int k = n; while(k > 0){ cout<<s[k]<<endl; k = k - s[k];

算法分析 | 动态规划 | 凸多边形的最优三角剖分问题

只谈情不闲聊 提交于 2020-02-08 01:21:44
学习自 https://www.jianshu.com/p/b97b0bb78b6c 一.问题分析: 将凸多边形内部划分成若干三角形,每一条线都带权 哪一种划法,让 三角形的权最小? 因其具有最优子结构: 所以,总问题的最优解=子问题的最优解+ 一个三角形的权 即 举例来说:当程序运行到i=0,j=5,k=3时: 设: 求解的是多边形{V0,V1,........Vn-1} bestWeight[ i ] [ j ] =m 表示它的一个子多边形{Vi , Vi+1 , ... , Vj-1 , Vj}的最优解=m (所以最终解为bsetWeight[ 0 ][ n-1 ]) bestPoint[ i ] [ j ] = k 表示该子多边形出现最优解时,构成的三角形为{ Vi , Vk , Vj }. 当i==j时,子问题退化成了点 ; 当i+1=j时,子问题退化成了一条线. 此时要退出,并且bestWeight[ i ] [ j ] =0;bestPoint[ i ] [ j ] = -1 二.代码实现 const int N = 6; vector<vector<int>> weight = {// 给出权函数。 {0, 2, 3, 1, 5, 6}, {2, 0, 3, 4, 8, 6}, {3, 3, 0, 10, 13, 7}, {1, 4, 10, 0, 12, 5},

动态规划—石子合并(直线和环)

非 Y 不嫁゛ 提交于 2020-02-07 00:06:12
先来看直线的: N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。 例如: 1 2 3 4,有不少合并方法 1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19) 1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24) 1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20) 括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。 Input 第1行:N(2 <= N <= 100) 第2 - N + 1:N堆石子的数量(1 <= A i i <= 10000) Output 输出最小合并代价 Sample Input 4 1 2 3 4 Sample Output 19 虽然知道这是一道dp题目,但是刚开始的时候怎么也想不出怎么做状态转移,于是又是blog和csdn一顿搜,终于搞出来了。 我们设dp[i][j]是从第i堆石子到第j堆石子合并的最小代价,sum[i]是前i堆石子的数量之和,那么状态转移方程就是: dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])