浙江大学 acm程序设计竞赛 动态规划讲义
合集下载
ACM竞赛之动态规划
第8讲:ACM竞赛之动态规划
8.2 DAG上的动态规划
8.2.1 DAG模型 例题:嵌套矩形(输出字典序最小解)
memset(G, 0, sizeof(G)); for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) if (x[i] < x[j] && y[i] < y[j]) G[i][j] = 1; ans = 0; for (i = 1; i <= n; i++) if (dp(i) > ans) { best = i; ans = dp(i); } printf("%d\n", ans); print_ans(best); printf("\n"); return 0; }
第8讲:ACM竞赛之动态规划
8.1 基本概念
例题:数字三角形 解决方法:动态划
状态转移方程:d(i,j)=a(i,j)+max{d(i+1,j),d(i+1,j+1)}
方法2:递推计算 可以用递推发法计算状态转移方程,其关键是边界和计算 顺序。在多数情况下,递推法的时间复杂度是:状态总数× 每个状态的决策个数×决策时间。如果不同状态的决策个数 不同,需具体问题具体分析。
第8讲:ACM竞赛之动态规划
8.1 基本概念
动态规划(dynamic programming)是运 筹学的一个分支,是求解决策过程 (decision process)最优化的数学方法。 20世纪50年代初美国数学家 R.E.Bellman等人在研究多阶段决策过 程(multistep decision process)的优化问 题时,提出了著名的最优化原理 (principle of optimality),把多阶段过程
浙大ACM简单讲解 1
总结比赛经验团队合作角色定位任务分工队长codingdebug一题读两遍赛前准备赛前准备熟悉题目编译器差异vc60编译通过但是在zoj编译出错devc中longlong的输入格式为i64d而zoj中为lld打印功能比赛进行时比赛策略全面开花vs孤注一掷输入输出输出格式如时间02d
Lecture I 比赛经验与编程技巧
– 得到右数第k位值 – 把右数第k位置1 – 把右数第k位取反 – 把最右边的1置0 – 把最右边的0置1 – 判断奇偶(最低位) (x >> k) & 1 x | (1 << k) x ^ (1 << k) x & (x – 1) x | (x + 1) x&1
枚举所有选取方式
• 枚举n个数中选一些的方式
熟悉比赛环境
• 熟悉交题、查看返回信息的方法 • 熟悉Runs中的Search功能 • 打印功能
比赛进行时
比赛策略
• 寻找简单题 • 看题、交流题意 • 观察气球、ranklist,跟风 • 打印、纸上调试 • 学会放弃 • 全面开花 vs 孤注一掷
输入输出
• 几种输入输出要求 • 负数和-1的区别 • 行内拆分(使用stringstream) • 输出格式,如时间”%02d:%02d:%02d”
• 申请新节点,并加到p节点后
– next[p] = ind++;
Standard C++ Library
C++风格头文件
• #include • #include • #include • #include • #include • #include • #include <iostream> <cstdio> <string> <cstring> <cmath> <vector> <algorithm>
Lecture I 比赛经验与编程技巧
– 得到右数第k位值 – 把右数第k位置1 – 把右数第k位取反 – 把最右边的1置0 – 把最右边的0置1 – 判断奇偶(最低位) (x >> k) & 1 x | (1 << k) x ^ (1 << k) x & (x – 1) x | (x + 1) x&1
枚举所有选取方式
• 枚举n个数中选一些的方式
熟悉比赛环境
• 熟悉交题、查看返回信息的方法 • 熟悉Runs中的Search功能 • 打印功能
比赛进行时
比赛策略
• 寻找简单题 • 看题、交流题意 • 观察气球、ranklist,跟风 • 打印、纸上调试 • 学会放弃 • 全面开花 vs 孤注一掷
输入输出
• 几种输入输出要求 • 负数和-1的区别 • 行内拆分(使用stringstream) • 输出格式,如时间”%02d:%02d:%02d”
• 申请新节点,并加到p节点后
– next[p] = ind++;
Standard C++ Library
C++风格头文件
• #include • #include • #include • #include • #include • #include • #include <iostream> <cstdio> <string> <cstring> <cmath> <vector> <algorithm>
ACM培训-动态规划
main() {
memset(save,0,sizeof(save )); int n; cin>>n; cout<<f(n );
动态规划的实质
可以看出动态规划的 实质就是
这就是为什么我们常说动态规划必须满 足重叠子问题的 原因.
记 忆 化 ,正符合了这个要求.
用动态规划法求解的问题具有特征: 能够分解为相互重叠的若干子问题; 满足最优性原理(也称子结构质):该问题的解中包含着其。
因此,在解这类问题时,一般采用动 态规划法。
动态规划法与贪心法的区别
区别1
动态规划法先求子问题的解,然后通过求解子问题构造原 问 题的解;
贪心算法是直接地解原问题。
区别2
动态规划法通过对若干局部最优解的比较,去掉了次优解 , 从而产生了更高一层次的局部最优解。
相当于对较低层次的局部最优解进行贪心的选择而得到高 一 级的局部最优解,因而最终产生一个最高层次的局部 最优 解。
记忆化搜索
Opt[i, j] - 每产生一个f(i, j),将f(i, j)的值放入opt中,以 后 再次调用到f(i, j)的时候,直接从opt[i, j]来取就可以 了。
于是动态规划的状态转移方程被直观地表示出来了,这 样 节省了思维的难度,减少了编程的技巧,而运行时间 只是 相差常数的复杂度,
则按子串sub的长度从大到小依次进行递推 求 解:
利用数字三角的思路
cost[i-2][ j+1] 若st[ j]=st[i+j1] Cost[i][ j]= min{cost[i-1][ j]+1,cost[i1][ j+1]+1}
ACM 培 训
memset(save,0,sizeof(save )); int n; cin>>n; cout<<f(n );
动态规划的实质
可以看出动态规划的 实质就是
这就是为什么我们常说动态规划必须满 足重叠子问题的 原因.
记 忆 化 ,正符合了这个要求.
用动态规划法求解的问题具有特征: 能够分解为相互重叠的若干子问题; 满足最优性原理(也称子结构质):该问题的解中包含着其。
因此,在解这类问题时,一般采用动 态规划法。
动态规划法与贪心法的区别
区别1
动态规划法先求子问题的解,然后通过求解子问题构造原 问 题的解;
贪心算法是直接地解原问题。
区别2
动态规划法通过对若干局部最优解的比较,去掉了次优解 , 从而产生了更高一层次的局部最优解。
相当于对较低层次的局部最优解进行贪心的选择而得到高 一 级的局部最优解,因而最终产生一个最高层次的局部 最优 解。
记忆化搜索
Opt[i, j] - 每产生一个f(i, j),将f(i, j)的值放入opt中,以 后 再次调用到f(i, j)的时候,直接从opt[i, j]来取就可以 了。
于是动态规划的状态转移方程被直观地表示出来了,这 样 节省了思维的难度,减少了编程的技巧,而运行时间 只是 相差常数的复杂度,
则按子串sub的长度从大到小依次进行递推 求 解:
利用数字三角的思路
cost[i-2][ j+1] 若st[ j]=st[i+j1] Cost[i][ j]= min{cost[i-1][ j]+1,cost[i1][ j+1]+1}
ACM 培 训
ACM课件13.递归与动态规划(二)
程序(二) 、参考程序 二
void tryToPut(int i) { if(i > 8) { //如果最后一个皇后被放置完毕,将当前解复制到全部解中 如果最后一个皇后被放置完毕, 如果最后一个皇后被放置完毕 for(int k = 1; k <= 8; k ++) record[count][k] = mark[k]; count ++; } for(int j=1; j<=8; j++) { //逐一尝试将当前皇后放置在不同列上 逐一尝试将当前皇后放置在不同列上 if(range[j] && line1 [i + j] && line2[i - j + 9]) //如果与前面不冲突 如果与前面不冲突 { mark[i] = j; range[j] = line1[i + j] = line2[i - j + 9] = false; tryToPut(i + 1); range[j] = line1[i + j] = line2[i - j + 9] = true;//回溯,撤销控制 回溯, 回溯 } } }
问题描述
输入数据 行是测试数据的组数n,后面跟着n 行输入。 第 1 行是测试数据的组数 ,后面跟着 行输入。每组测试数 据占1 包括一个正整数b(1 <= b <= 92) 据占 行,包括一个正整数 输出要求 n 行,每行输出对应一个输入。输出应是一个正整数,是对应 每行输出对应一个输入。输出应是一个正整数, 于b 的皇后串 输入样例 2 1 92 输出样例 15863724 84136275
3/34
3、解题思路(一) 、解题思路 一
void tryToPut(int i) { if(i > 8) { //如果最后一个皇后被放置完毕,将当前解复制到全部解中 如果最后一个皇后被放置完毕, 如果最后一个皇后被放置完毕 for(int k = 1; k <= 8; k ++) record[count][k] = mark[k]; count ++; } for(int j=1; j<=8; j++) { //逐一尝试将当前皇后放置在不同列上 逐一尝试将当前皇后放置在不同列上 if(range[j] && line1 [i + j] && line2[i - j + 9]) //如果与前面不冲突 如果与前面不冲突 { mark[i] = j; range[j] = line1[i + j] = line2[i - j + 9] = false; tryToPut(i + 1); range[j] = line1[i + j] = line2[i - j + 9] = true;//回溯,撤销控制 回溯, 回溯 } } }
问题描述
输入数据 行是测试数据的组数n,后面跟着n 行输入。 第 1 行是测试数据的组数 ,后面跟着 行输入。每组测试数 据占1 包括一个正整数b(1 <= b <= 92) 据占 行,包括一个正整数 输出要求 n 行,每行输出对应一个输入。输出应是一个正整数,是对应 每行输出对应一个输入。输出应是一个正整数, 于b 的皇后串 输入样例 2 1 92 输出样例 15863724 84136275
3/34
3、解题思路(一) 、解题思路 一
ACM程序设计竞赛II第一章ppt课件
#include<stdio.h> const int MAXN = 1000; int n, left[MAXN], right[MAXN];
void link(int X, int Y) { right[X] = Y; left[Y] = X;
}
int main() { int m, X, Y; char type[9]; scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { left[i] = i-1; right[i] = i+1; } for(int i = 0; i < m; i++) { scanf("%s%d%d", &type, &X, &Y); link(left[X], right[X]); if(type[0] == 'A') { link(left[Y], X); link(X, Y); } else { link(X, right[Y]); link(Y, X); } } for(int X = right[0]; X != n+1; X = right[X]) printf("%d ", X); printf("\n"); return 0;
• 输出:每一行一个整数x,对应一组case,表示该组case的 字符串中所包含的最长回文长度.
• aaaa
• abab
•4 •3
完整版PPT课件
6
int i,j; int max,m; while(scanf("%s",&s)!=EOF) {
杭电acm初学者通用课件
该竞赛旨在通过解决一系列复杂的编程问题,来考察参赛者 的算法设计、数据结构选择、编程技巧等方面的能力,以及 团队协作和解决问题的能力。
ACM/ICPC的意义
1 2 3
提高编程能力和算法设计能力
ACM/ICPC的题目通常涉及各种算法和数据结构 ,通过解决这些题目,可以提高编程能力和算法 设计能力。
培养团队协作和沟通能力
入/删除操作。
树形数据结构
包括二叉树、多叉树、B树 等。这些数据结构用于表 示层次关系和进行高效的
查找操作。
图数据结构
由节点和边组成的数据结 构,用于表示对象之间的 关系。常见的图数据结构 有邻接矩阵和邻接表等。
03
刷题技巧
如何选题
难度适中
选择难度适中的题目,逐步提升解题能力 。
覆盖面广
尽量选择涉及多种知识点的题目,提高知 识掌握的全面性。
对算法的原理和实现细节理解不足,导致 在解题过程中出现错误。
代码实现错误
由于编程语言和技巧不熟练,导致代码实 现出现错误。
忽视题目要求
在解题过程中忽视题目的特殊要求,导致 答案不符合题目要求。
高分选手的共性
01 良好的数学基础
高分选手通常具备扎实的数学 基础,能够快速理解和运用数 学原理。
02 高效的算法思维
详细描述
参与开源项目可以了解实 际项目中的算法和数据结 构应用,组织线上讨论可 以与其他人交流学习经验 ,拓宽视野和思路。
总结词
积极参与开源社区和线上 讨论。
详细描述
通过参与开源社区和线上 讨论,可以了解最新的技 术动态和趋势,同时也可 以结交志同道合的朋友, 共同进步。
06
结束语
不断实践和学习
高分选手在解题时能够迅速找 到合适的算法,并高效实现。
ACM/ICPC的意义
1 2 3
提高编程能力和算法设计能力
ACM/ICPC的题目通常涉及各种算法和数据结构 ,通过解决这些题目,可以提高编程能力和算法 设计能力。
培养团队协作和沟通能力
入/删除操作。
树形数据结构
包括二叉树、多叉树、B树 等。这些数据结构用于表 示层次关系和进行高效的
查找操作。
图数据结构
由节点和边组成的数据结 构,用于表示对象之间的 关系。常见的图数据结构 有邻接矩阵和邻接表等。
03
刷题技巧
如何选题
难度适中
选择难度适中的题目,逐步提升解题能力 。
覆盖面广
尽量选择涉及多种知识点的题目,提高知 识掌握的全面性。
对算法的原理和实现细节理解不足,导致 在解题过程中出现错误。
代码实现错误
由于编程语言和技巧不熟练,导致代码实 现出现错误。
忽视题目要求
在解题过程中忽视题目的特殊要求,导致 答案不符合题目要求。
高分选手的共性
01 良好的数学基础
高分选手通常具备扎实的数学 基础,能够快速理解和运用数 学原理。
02 高效的算法思维
详细描述
参与开源项目可以了解实 际项目中的算法和数据结 构应用,组织线上讨论可 以与其他人交流学习经验 ,拓宽视野和思路。
总结词
积极参与开源社区和线上 讨论。
详细描述
通过参与开源社区和线上 讨论,可以了解最新的技 术动态和趋势,同时也可 以结交志同道合的朋友, 共同进步。
06
结束语
不断实践和学习
高分选手在解题时能够迅速找 到合适的算法,并高效实现。
浙江大学_acm程序设计竞赛_培训_线段树68页PPT
Thank you
•
29、在一切能够接受法律支配的人类 的状态 中,哪 里没有 法律, 那里就 没有自 由。— —洛克
•
30、风俗可以造就法律,也可以废除 法律。 ——塞·约翰逊
线段树
6、最大的骄傲于最大的自卑都表示心灵的最软弱无力。——斯宾诺莎 7、自知之明是最难得的知识。——西班牙 8、勇气通往天堂,怯懦通往地狱。——塞内加 9、有时候读书是一种巧妙地避开思考的方法。——赫尔普斯 10、阅读一切好书如同和过去最杰出的人谈话。——笛卡儿
浙江大学_acm程序设计竞赛_培训_
•
26、我们像鹰一样,生来就是自由的 ,但是 为了生 存,我 们不得 不为自 己编织 一个笼 子,然 后把自 己关在 里面。 ——博 莱索
•
27、法律如果不讲道理,即使延续时 间再长 ,也还 是没有 制约力 的。— —爱·科 克
•
28、好法律是由坏风俗创造出来的。 ——马 克罗维 乌斯
•
29、在一切能够接受法律支配的人类 的状态 中,哪 里没有 法律, 那里就 没有自 由。— —洛克
•
30、风俗可以造就法律,也可以废除 法律。 ——塞·约翰逊
线段树
6、最大的骄傲于最大的自卑都表示心灵的最软弱无力。——斯宾诺莎 7、自知之明是最难得的知识。——西班牙 8、勇气通往天堂,怯懦通往地狱。——塞内加 9、有时候读书是一种巧妙地避开思考的方法。——赫尔普斯 10、阅读一切好书如同和过去最杰出的人谈话。——笛卡儿
浙江大学_acm程序设计竞赛_培训_
•
26、我们像鹰一样,生来就是自由的 ,但是 为了生 存,我 们不得 不为自 己编织 一个笼 子,然 后把自 己关在 里面。 ——博 莱索
•
27、法律如果不讲道理,即使延续时 间再长 ,也还 是没有 制约力 的。— —爱·科 克
•
28、好法律是由坏风俗创造出来的。 ——马 克罗维 乌斯
ACM课件(lecture_04)动态规划(1).
33 2019/8/9
思考:免费馅饼
34 2019/8/9
如何解决?
请发表见解
35 2019/8/9
Any Question?
36 2019/8/9
附录:DP练习题(HDOJ):
1003、1087、1159、1160、1176 1024、1025、1058、1069、1081 1074、1157、1158、1466
试想一下:
这道题如果用枚举法(暴力思想),在数 塔层数稍大的情况下(如31),则需要列 举出的路径条数将是一个非常庞大的数目 (2^30= 1024^3 > 10^9=10亿)。
13 2019/8/9
所以,不可以如此暴力!!!
14 2019/8/9
考虑一下:
从顶点出发时到底向左走还是向右走应取决 于是从左走能取到最大值还是从右走能取到最大 值,只要左右两道路径上的最大值求出来了才能 作出决策。
1078、1080、1114 1203、1294、1227、1223 1500、1501、1502、1503 1505、1506、1510、2059
37 2019/8/9
课后一定要练习! DP”相-当-”重要!
38 2019/8/9
有志于参加竞赛的同学, 加油!!!
39 2019/8/9
最优解。
其中(1)——(3)步是动态规划算法的 基本步骤。在只需要求出最优值的情形,步骤 (4)可以省去。若需要求出问题的一个最优 解,则必须执行步骤(4)。此时,在步骤(3) 中计算最优值时,通常需记录更多的信息,以 便在步骤(4)中,根据所记录的信息,快速 构造出一个最优解。
32 2019/8/9
(n-2)*2+0=4 或者 (n-2)*2+1=5 4、 第四条直线不与任何一条直线平行,交点数为:
思考:免费馅饼
34 2019/8/9
如何解决?
请发表见解
35 2019/8/9
Any Question?
36 2019/8/9
附录:DP练习题(HDOJ):
1003、1087、1159、1160、1176 1024、1025、1058、1069、1081 1074、1157、1158、1466
试想一下:
这道题如果用枚举法(暴力思想),在数 塔层数稍大的情况下(如31),则需要列 举出的路径条数将是一个非常庞大的数目 (2^30= 1024^3 > 10^9=10亿)。
13 2019/8/9
所以,不可以如此暴力!!!
14 2019/8/9
考虑一下:
从顶点出发时到底向左走还是向右走应取决 于是从左走能取到最大值还是从右走能取到最大 值,只要左右两道路径上的最大值求出来了才能 作出决策。
1078、1080、1114 1203、1294、1227、1223 1500、1501、1502、1503 1505、1506、1510、2059
37 2019/8/9
课后一定要练习! DP”相-当-”重要!
38 2019/8/9
有志于参加竞赛的同学, 加油!!!
39 2019/8/9
最优解。
其中(1)——(3)步是动态规划算法的 基本步骤。在只需要求出最优值的情形,步骤 (4)可以省去。若需要求出问题的一个最优 解,则必须执行步骤(4)。此时,在步骤(3) 中计算最优值时,通常需记录更多的信息,以 便在步骤(4)中,根据所记录的信息,快速 构造出一个最优解。
32 2019/8/9
(n-2)*2+0=4 或者 (n-2)*2+1=5 4、 第四条直线不与任何一条直线平行,交点数为:
浙江大学acm程序设计竞赛动态规划讲义.ppt
买 车 票
怎 么 办
当前所在的某个车站
买
车
票
这一题的以前状态其实只有3种.即 满足3种距离(收费)情况的3个车站.
要知道这3个车站可以先做一个预
段
状态.但阶段不是以前状态,状态是
决 策
阶段的表现形式.数字三角形的以前 状态就是当前层的前一层.
那什么是决策呢?我们看看下面一
张图就知道了.
显然,从上图可以看出,当前状态通
决 过决策,回到了以前状态.可见决策 策 其实就是状态之间的桥梁。而以前
状态也就决定了当前状态的情况。
数字三角形的决策就是选择相邻的两 个以前状态的最优值。
动
规 的
我们一般在动规的时候所用到的一
些数组,也就是用来存储每个状态 的最优值的。
要
我们就从动态规划的要诀,也就是
诀
核心部分“状态”开始,来逐步了
-
解动态规划。
状
态
拦截导弹(Noip2002)
某国为了防御敌国的导弹袭击,发
展出一种导弹拦截系统。但是这种
拦
导弹拦截系统 有一个缺陷:虽然它 的第一发炮弹能够到达任意的高度,
也就是把产生过的最优状态,又产
生了一次。为了避免浪费,很显然,
我们存放一个opt数组:
Opt[i, j] - 每产生一个f(i, j),
将f(i, j)的值放入opt中,以后再
次调用到f(i, j)的时候,直接从
记 忆
opt[i, j]来取就可以了。
于是动态规划的记状忆态化转移的方功程效被直
化 搜 索
数
+ min{f(i-1, j)+f(i-1, j + 1)}
字
DP动态规划ACM课件
}
return sum;
}
引申问题: 最大子矩阵和问题 最大m段子段和问题
▪ 最长递增子序列(LIS)
▪ 常规DP,时间复杂度为O(n2)。
▪ 存在一种特殊的方法,时间复杂度为 O(n*logk)。
▪ 推荐题目: POJ1631 Bridging Signals
POJ1631参考代码
▪ #include<iostream>
▪
for(i=1;i<=n;i++)
▪
scanf("%d%d",&v[i][0],&v[i][1]);
▪
l=l*1000;
▪
if(l >= 450000) {printf("0\n");continue;}
▪
memset(f,0,sizeof(int)*(l+1));
▪
memset(fff,0,sizeof(fff));
E 阶段4
▪ 设 Dis[k][x] 为第k阶段城市x到城市E的最短路径长度。 map[ i ][ j ]为i,j两个城市间的距离。
▪ 递归方程为 Dis[k][x] = min { Dis[k+1][y]+map[x,y] }
▪ 此问题时间复杂度降为O(n2).
▪ 状态:贴切,简洁的描述出事物性质的单元量。例如: Dis[x]。 要求:状态与状态之间可以转移,以便有初始状态逐渐转移 到目标状态,找到问题的解。
▪ 阶段:若干性质相近可以同时处理的状态的集合。就是计算 状态的顺序。 要求:每个阶段中状态的取值只与这个阶段之前的阶段中的 状态有关,与这个阶段之后的阶段中的状态无关。
▪ 状态转移方程:前一个阶段中的状态转移到后一个 阶段的状态得演变规律,即相邻两个阶段的状态变 化方程。
return sum;
}
引申问题: 最大子矩阵和问题 最大m段子段和问题
▪ 最长递增子序列(LIS)
▪ 常规DP,时间复杂度为O(n2)。
▪ 存在一种特殊的方法,时间复杂度为 O(n*logk)。
▪ 推荐题目: POJ1631 Bridging Signals
POJ1631参考代码
▪ #include<iostream>
▪
for(i=1;i<=n;i++)
▪
scanf("%d%d",&v[i][0],&v[i][1]);
▪
l=l*1000;
▪
if(l >= 450000) {printf("0\n");continue;}
▪
memset(f,0,sizeof(int)*(l+1));
▪
memset(fff,0,sizeof(fff));
E 阶段4
▪ 设 Dis[k][x] 为第k阶段城市x到城市E的最短路径长度。 map[ i ][ j ]为i,j两个城市间的距离。
▪ 递归方程为 Dis[k][x] = min { Dis[k+1][y]+map[x,y] }
▪ 此问题时间复杂度降为O(n2).
▪ 状态:贴切,简洁的描述出事物性质的单元量。例如: Dis[x]。 要求:状态与状态之间可以转移,以便有初始状态逐渐转移 到目标状态,找到问题的解。
▪ 阶段:若干性质相近可以同时处理的状态的集合。就是计算 状态的顺序。 要求:每个阶段中状态的取值只与这个阶段之前的阶段中的 状态有关,与这个阶段之后的阶段中的状态无关。
▪ 状态转移方程:前一个阶段中的状态转移到后一个 阶段的状态得演变规律,即相邻两个阶段的状态变 化方程。
ACM课件 动态规划
• 所有的海盗都乐于看到他们的一位同伙被扔 进海里,不过,如果让他们选择的话,他们 还是宁可得一笔现金。他们当然也不愿意自 己被扔到海里。
• 所有的海盗都是聪明绝顶的,而且知道其他 的海盗也是聪明绝顶的。
• 此外,没有两名海盗是同等厉害的——这些 海盗按照完全由上到下的等级排好了座次, 并且每个人都清楚自己和其他所有人的等级。
(4)C1,C2,C3是第二次输入结点,他们到D1, D2各有两种费用。此时应计算C1,C2,C3分别到E 的最少费用。 f(C1) =min{C1D1+ f(D1) ,C1D2+ f(D2)}。
• 3号海盗的分配方案:3号海盗分得99块 金子,2号海盗一无所获,1号海盗得1块 金子。
•1号海盗知道,如果3号的方案被否决,那么最后 将只剩2个海盗,而1号将肯定一无所获——此外, 3号也明白1号了解这一形势。因此,只要3号的分 配方案给1号一点甜头使他不至于空手而归,那么 不论3号提出什么样的分配方案,1号都将投赞成票。 因此3号需要分出尽可能少的一点金子来贿赂1号海 盗
• 4号的分配方案应是:99块金子归自己,3 号一块也得不到,2号得1块金子,1号也是 一块也得不到。
4号海盗的策略也差不多。他需要有50%的支 持票,因此同3号一样也需再找一人做同党。 他可以给同党的最低贿赂是1块金子,而他可 以用这块金子来收买2号海盗。因为如果4号被 否决而3号得以通过,则2号将一文不名。
• 除起点A和终点E外,其它各点既是上一阶 段的终点又是下一阶段的起点。
例若在如选第从择二AB阶2到的段B决,的策再第,从一BB阶22就段点是中出第,发一A,为阶对起段于点在B,2我点终们就点决有有策一B之个1,下可的供 B结选2果两择,个的它,终既因点是而集第这合一时(C阶走1,段的C路路2线,线的C有3终两);点个若,选选又择择是,由第一B二是2走阶走至段到C路B21为线, 一的第是始二走点阶到。段B的2。决策,则C2就是第二阶段的终点,同时又 是第三阶段的始点。
ACM培训03-动态规划
p( q+1,r,k-1 )
d ( l , q )= s[l] s[l+1]…s[q]
q的变化范围:从q+1到r之间所包含 的数字个数应大于k-1(乘号个数)。
r-(q+1)+1>k-1 q<r-k+1
p( l,r,k )=max{ d( l, q ) * p( q+1, r ,k-1 ) }
状态转移方程:用数学公式描述与阶段相 关的状态间的演变规律。
动态规划是运筹学的一个重要分支,是解 决多阶段决策过程最优化的一种方法。
所谓多阶段决策过程,是将所研究的过程 划分为若干个相互联系的阶段,在求解 时,对每一个阶段都要做出决策,前一 个决策确定以后,常常会影响下一个阶 段的决策。
动态规划所依据的是“最优性原理”。
显然,要依照上述递推过程求解,需要倒 过来,从P(P)出发,先求出第一阶段的P(O) 和P(N),再求第二阶段的P(K),P(L), P(M);……,最后得到P(A)。
3. 选择数据结构,将每条路经的长度存在数 组中。
东西方向上的道路长度存在两维数组h[4][3]中规 定数组的第一维为行号,第二维为列号。
10 动态规划
任务:
P是出发点,从P到A,求最短路径(图1)
G
3 D 1B 2
A
1
2
2
3
K
3 H
4 E
5
4
1
2
N
2 L
1 I
4
2
2
3
3
2
3
C
4
阶段5
F
4 阶段4
P
O
M
J
阶段1
阶段2 阶段3
ACM 程序设计竞赛入门:第9讲 动态规划(2)
2020/12/10
4
例题2-1:最长递增子序列
i 012 3 4 5 6 7 8 Num[i] 1 4 7 2 5 8 3 6 9
2020/12/10
5
状态转移方程:
动态规划的状态表示描述为: m[i] ( 1≤i≤n ) 表 示 以 num[i] 结 尾 的 最 长
上升子序列的长度。
状态转移方程: m[i]=1+max{0,m[k]|x[k]<x[i],
证明:假设四个从小到大的数:a、b、c、 d,只需证明以下表达式成立即可:
(a-b)^2+(c-d)^2< (a-c)^2+(b-d)^2
(a-b)^2+(c-d)^2< (a-d)^2+(b-c)^2 ……(略)
2020/12/10
10
预备工作:
排序!
2020/12/10
11
第二感觉:
第九讲
动态规划(2)
(Dynamic programming)
2020/12/10
1
一、动态规划的基本思想
基础思想来自分治策略后面的直觉
人们通过细心地把问题分解成一系列子问题, 然后对越来越大的问题建立正确的解。
•不同的子问题的个数只是多项式量级; •可以容易地从子问题的解计算初始问题 的解; •在子问题从“最小”到“最大”。存在 一种自然的顺序,与一个容易计算的递 推式相联系。
1≤k<i } 问题的解: max{m[i],1≤i≤n},
2020/12/10
6
M[i]的计算:
i 012 3 4 5 6 7 8 Num[i] 1 4 7 2 5 8 3 6 9
m[i] 1 2 3 2 3 4 3 4 5
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Tom
的 烦 恼
Tom的烦恼 按结束时间排序,枚举结束时间作为 当前状态,以前状态就是该结束时间 对应的起始时间,这是已经确定的.
Tom
文 字 游 戏
文字游戏(fairfox邀请赛1) 给你一份单词表,和一个句子。求出该句 子能有多少中不同的划分方法.例如: 单词是ab cd a b c d 句子是abcd 他共有4种完全划分方案: ab/cd a/b/c/d a/b/cd ab/c/d; 当前状态就是单词在句子中向后靠的位置, 以前状态就是确定这个单词位置以后,除 掉这个单词长度后的一个位置.状态转移 方程是:F[i]:=F[i]+F[ilength(word[j])] IOI中有一题《前缀》也是类似的题目.
拦 截 导 弹
拦 截 导 弹
状态的表示-f[i],表示当第i个导 弹必须选择时,前i个导弹最多能拦 截多少。 每个导弹有一定的高度,当前状态 就是以第i个导弹为最后一个打的导 弹。以前状态就是在这个导弹以前 打的那个导弹。 显然这是十分能够体现状态间的联 系的题目。
最 长 公 共 子 串
给定起点站和终点站还有 L1,L2,L3,C1,C2,C3,求出要从 起点到终点最少要花多少钱.
买 车 票
怎 么 办
当前所在的某个车站
买 车 票
这一题的以前状态其实只有3种.即 满足3种距离(收费)情况的3个车站. 要知道这3个车站可以先做一个预 处理.显然这3个车站在满足距离限 制的条件下应该越远越好.
可以看出动态规划的实质就是
动 态 规 划 的 实 质
这也就是为什么我们常说动态 规划必须满足重叠子问题的原 因.记忆化,正符合了这个要求.
状 态 阶 段 决 策
或许有一种对动态规划的简单 称法,叫分阶段决策.其实我认为 这个称法并不是很能让人理解. 那么下面我们来看看阶段,状态, 决策这三者间得关系吧.
给出两个字符串序列。求出这 样的一个最长的公共子串:子 串中的每个字符都能在两个原 串中找到,而且每个字符的顺 序和原串中的顺序一致。
交错匹配(最长公共子串的改编)
给你两排数字,只能将两排中数字相同的两个位置 相连,而每次相连必须有两个匹配形成一次交错,交 错的连线不能再和别的交错连线有交点.问这两排 数字最多能形成多少个交错匹配.
交 错 匹 配
1 3
2 1
3 2
3 3
2 2
4 4
1 12
5 1
1 5
3 5
5 3
10
状态的表示-f[i,j]表示前i个第一排的数 字和前j个第二排的数字搭配的最优值。 当前的状态就是当前你枚举到的一组交错 的后面两个位置.例如上图中当前状态是3 和1(第一组交错),枚举他的以前状态就有1 3.这样在1 3之前会有一个最优值存在,因 此可以由此得到3 1的最优值.
最 佳 加 法 表 达 式
用f[i,j],表示的是在前i个字符中 插入j个加号能达到的最小值,最 后的答案也就是F[length(s),m]. 于是就有一个动规的方程: F[i,j]:=min(f[i,j],f[k,j1]+num[k+1,i]) num[k+1,i]表 示k+1位到i位所形成的数字.这 里显然是把加号插入了第k+1个 位置上. 知道了这一题怎么做以后,乘积 最大的一题也是完全一样的形式, 谁还会去用搜索?
决 策 中 的 定 量
状态转移方程的构造无疑是动态 规划过程中最重要的一步,也是 最难的一步.对于大多数的动态 规划,寻找状态转移方程有一条 十分高效的通道,就是寻找变化 中的不变量.定量处理的过程也 就是决策实施的过程.
或许你不明白我在说什么,那 么我们通过题目来说明吧
寻 找 定 量
最佳加法表达式 有一个由1..9组成的数字串. 问如果将m个加号插入到这个 数字串中.使得所形成的算术 表达式的值最小.
什 么 是 动 态 规 划
在学习动态规划之前你一定学 过搜索.那么搜索与动态规划有 什么关系呢?我们来下面的一 个例子.
数 字 三 角 形
给你一个数字三角形, 形式如下: 1 2 3 4 5 6 7 8 9 10 找出从第一层到最后一层的一条 路,使得所经过的权值之和最小或 者最大.
数 字 三 角 形
拦截导弹(Noip2002) 某国为了防御敌国的导弹袭击,发 展出一种导弹拦截系统。但是这种 导弹拦截系统 有一个缺陷:虽然它 的第一发炮弹能够到达任意的高度, 但是以后每一发炮弹都不能高 于前 一发的高度。 某天,雷达捕捉到敌 国的导弹来袭。由于该系统还在试 用阶段,所以 只有一套系统,因此 有可能不能拦截所有的导弹。输入 导弹依次飞来的高度,计算这套系 统最多能拦截多少导弹。
ቤተ መጻሕፍቲ ባይዱ
记 忆 化 搜 索
Opt[i, j] - 每产生一个f(i, j), 将f(i, j)的值放入opt中,以后再 次调用到f(i, j)的时候,直接从 opt[i, j]来取就可以了。 记忆化的功效 于是动态规划的状态转移方程被直 观地表示出来了,这样节省了思维 的难度,减少了编程的技巧,而运 行时间只是相差常数的复杂度,而 且在相当多的情况下,递归算法能 更好地避免浪费,在比赛中是非常 实用的.
记 忆 化 搜 索
我们尝试从正面的思路去分析问题, 如上例,不难得出一个非常简单的 递归过程 : f1:=f(i-1,j+1); f2:=f(i-1,j); if f1>f2 then f:=f1+a[i,j] else f:=f2+a[i,j]; 显而易见,这个算法就是最简单的 搜索算法。时间复杂度为2n,明显 是会超时的。分析一下搜索的过程, 实际上,很多调用都是不必要的, 也就是把产生过的最优状态,又产 生了一次。为了避免浪费,很显然, 我们存放一个opt数组:
状 态 阶 段 决 策
状态是表现出动态规划核心思想的 一个东西.而分阶段决策这个东西有 似乎没有提到状态,这是不科学的. 阶段,有些题目并不一定表现出一定 的阶段性.数字三角形的阶段就是每 一层.这里我们引入一个概念---以前 状态.但阶段不是以前状态,状态是 阶段的表现形式.数字三角形的以前 状态就是当前层的前一层. 那什么是决策呢?我们看看下面一 张图就知道了.
决 策
显然,从上图可以看出,当前状态通 过决策,回到了以前状态.可见决策 其实就是状态之间的桥梁。而以前 状态也就决定了当前状态的情况。
数字三角形的决策就是选择相邻的两 个以前状态的最优值。
动 规 的 要 诀 - 状 态
我们一般在动规的时候所用到的一 些数组,也就是用来存储每个状态 的最优值的。 我们就从动态规划的要诀,也就是 核心部分“状态”开始,来逐步了 解动态规划。
买 车 票
预处理 很容易想出一个N^2的预处理,但是那 样是会超时的.由于尽量要让车站离得 远(费用是一样的啊 )因此在每种收 费情况下,每个车站的以前状态车站一 定是递增的序列.这里是只要O(N)的程 序:
for j:=1 to 3 do begin k:=en-1; for i:=en downto be do begin while (way[i]-way[k]<=l[j])and(k>=be) do dec(k); p[i][j]:=k+1; end; end;
现在大概大家已经了解了定量 是什么,那么我们下面通过几道 题目来了解一下定量的威力.
定 量
游 戏
游戏(Noip2003普及组) 这一题的描述简单说一下:在一 个圈的周围有n个石子,将他们 划分成m堆(每堆中的石子必须 连续相邻),每一堆石子计算出 他们的总重量mod10的值,然后 将这些值相乘,求得到的结果最 大最小值是多少.
买 车 票
买车票(Ural1031) Ekaterinburg城到Sverdlovsk 城有直线形的铁路线。 两城之间还有其他一些停靠站, 总站数为N。 各站按照离Ekaterinburg城的 距离编号。 Ekaterinburg城编号为1, Sverdlovsk城编号为N。
买 车 票
某两站之间车票价格由这两站的距离X决定. 当0<X<=L1时,票价为C1元. 当L1<X<=L2时,票价为C2元. 当L2<X<=L3时,票价为C3元. 当两站距离大于L3时没有直达票,所以有时候要买几 次票做几次车才行。 比如,在上面的例图中,2-6没有直达票,有几种买 票 方法可以从2-6,其中一种是买C2元的2-3车票,再买 C3元的3-6车票。
最 佳 加 法 表 达 式
这一题中的定量是什么呢?因为是添 入加号,那么添完加号后,表达式的最 后一定是个数字串,这就是定量.从这 里入手,不难发现可以把以前状态认 为是在前i个字符中插入k-1个加号 (这里的i是当作决策在枚举),然后i+1 到最后一位一定是整个没有被分割 的数字串,第k个加号就添在i与i+1个 数字之间.这样就构造出了整个数字 串的最优解.而至于前i个字符中插入 k-1个加号,这又回到了原问题的形 式,也就是回到了以前状态,所以状态 转移方程就能很快的构造出来了.
数组P[i][j]表示的是I状态的第j种以前状态.
动态规划的部分
for i:=be+1 to en do {枚举当前状态} begin cost[i]:=maxlongint; for j:=1 to 3 do {枚举以前状态} begin if (p[i][j]<>i) and (cost[i] > cost[p[i][j]] + c[j]) then cost[i]:=cost[p[i][j]]+c[j]; end; end;