关于动态规划:
动态规划的重要性我不必强调了,从06年开始或多或少年年有的一个科目。现在大家对动态规划的理解已经基本不错了,再强化一下更好。希望大家能够在开学半个月之内彻底解决本文所说的所有内容。因为开学考试的问题,不难为你们也不难为我。
Common动态规划基本性质是对于每个子问题是无后效性的。鉴于这个问题,对于一些图论问题,如果图是”有向无环图”,那么显然满足无后效性。如果图有环,那么可以考虑将环去掉,或者使用SPFA的动态规划。
1、 理解与分析
读到题目首先肯定是要理解题目的内容。阅读理解是智商。但是OI的事实是很多题目都没能说清自己想要干嘛,再加上像我这样理解偏激的就可能遇见困难。碰见这样的题目不要纠结,问问同学这个题目想干嘛。题目的内容价值性将决定你做题的心情。
对于题目的分析,在你掌握一个OI科目的基础基础上,要将不会的问题转化为已经学过的问题解决。巧妙的转化可以顺利解决一些看似复杂的问题。比如下面这个问题,实际上你会做,只是你不知道。
题目1:地铁重组
问题描述
蒙提在暴风城与铁炉堡之间的地铁站中工作了许多年,除了每天抓一些矿道老鼠外,没有其他的变化。然而最近地铁站终于要扩建了,因为侏儒们攻克了建设长距离穿海隧道的技术难题,矮人们制造的炸药威力也有了很大的增强。于是,联盟决定修建通往诺森德的地铁。拥有常年的地铁站工作经验的蒙提被派往了新的线路上,他的工作是进行地铁重组。
如上图,在左边部分停靠着N节车厢,从右向左标号依次为1、2、……、N。中间有一个停车轨道,这个轨道上最多只能同时停放P节车厢。现在需要将左边轨道上的车厢驶入右边的轨道。每节车厢必须进入一次停车轨道进行检修,然后才能去右边的轨道。侏儒制造的每节车厢都有完整的动力装置,不需要依赖车头的带动。对于一个给定的停车轨道的大小P和左边轨道的车厢的数目N,蒙提想知道,这些车厢到右边轨道以后,有多少种不同的排列顺序。
输入格式
第1行:两个整数N,P。
输出格式
第1行:一个整数a,为排列顺序数除以4096的余数。
样例输入
3 2
样例输出
4
数据规模
对于70%的数据
1 <= N <= 500
1 <= P <= 300
对于100%的数据
1 <= N <= 2000
1 <= P <= 2000
看见这个题目你或许会一头雾水。题目大意是,给定一个栈,有N个数先后压入到栈中并不时弹出栈顶,最终得到的输出序列的方案数。没思路?看下面这个问题。
题目2:最小伤害
问题描述
把儿站在一个N x N的方阵中最左上角的格子里。他可以从一个格子走到它右边和下边的格子里。每一个格子都有一个伤害值。他想在受伤害最小的情况下走到方阵的最右下角。
输入数据
第一行输入一个正整数n。
以下n行描述该矩阵。矩阵中的数保证是不超过1000的正整数。
输出数据
输出最小伤害值。
样例输入
3
1 3 3
2 2 2
3 1 2
样例输出
8
数据规模
n<=1000
这两道题目几乎是一样的。不懂?翻到页后,便是这两道题的题解。不过建议你先考虑一下这两道题的关系,然后再决定是不是看答案。事实上连题目1的题解讲的都不如我解释的清晰,至少我看那个题解没看懂。
(本篇接下来的题目3的题解也在页后的题解中。)
2、 计数与最优解
动态规划的基本目的分为计数与最优解。一些题目的目的是求得最优解,比如背包问题、奶牛的锻炼、乘法游戏、机器分配。一些题目的目的是求得总的方案数量,比如传球游戏、地铁重组(题目1)。
需要特别留意的是,动态规划问题(特别是求方案数量的问题)结果可能很大很大,通常碰见动态规划题,你需要判断结果可能的范围。如果觉得结果超过了maxlongint,那么你需要考虑使用高精度(NOIP2007TG矩阵取数游戏)或者使用longlongint(int64)(NOIP2011TG选择客栈)。
更一般的情况是出题者明确的通知你题目可能会超出正常的int表示范围,从而让你将结果取模一个固定的数值然后输出(NOIP2011TG计算系数)。这个取模的数值通常是一个质数,常见的有10007,1000000007,32767。
应对策略是,有:(a + b) % c == (a % c + b % c) % c,(a * b) % c == (a % c * b % c) % c。也就是说,可以每步计算出来的结果都取模这个固定的值,那么最终的结果也取模这个值。对于一般含有加法和乘法的题目中,仅采用这种方法就可以解决。如果运算中包含减法,那么就很有研究……在不同的环境(系统、编译器版本)下,负数取模会得到不同的结果,一些会得到一个最小的正数,一些会得到最大的负数,总之就是会出错。如果需要用(a – b) % c,那么一定要在取模之后将结果再加上c,然后再取模。这样做可以保证这个结果是一个正数,同样容易解决。如果结果中包含除法……对不起我写文章的这一天白天教师讲的时候没学明白这个问题总之对你们来说很复杂再想别的办法吧……
特别注意的一点,在取模的时候,如果要求你取模的数正好是2的几次幂,如32768或者4096,那么你可以采取与32767(4095)相”与”的做法来更高效的取模。这里只是一提,在讲状态压