(总结一)poj简单动态规划
(总结一)poj简单动态规划
例1:求一维数组中连续数之和的最大值。
代码:#include<iostream>using namespace std;int a[100];//记录一维数组int res[100];//res[i]表示以第i个数为末尾的连续数之和的最大值int main(){int i,n,max;while(1){cin>>n;if(!n) break;memset(res,0,sizeof(a)),max=-1270000;for(i=0;i<n;i++){cin>>a[i];res[i]=a[i];if(i>0 && res[i-1]>0) res[i]+=res[i-1];//动态规划法if(res[i]>max) max=res[i];//打擂法}cout<<max<<endl;}return 0;}例2(poj1050):求二维数组中子矩阵之和的最大值。
(例1的拓展)代码:#include<iostream>using namespace std;int a[101][101];//记录二维数组int sum[101][101];//sum[i][j]表示第j列前i行的数之和int res[101][101][101];//res[i1][i2][j]表示从第i1行到第i2行,以第j个数为末尾的连续数之和的最大值int main(){int i,i1,i2,j,n,temp,max;while(1){cin>>n;if(!n) break;memset(sum,0,sizeof(sum)),memset(res,0,sizeof(res));for(i=1;i<=n;i++)for(j=1;j<=n;j++){cin>>a[i][j];//输入二维数组sum[i][j]=sum[i-1][j]+a[i][j];//求第j列前i行之和}max=-1270000;for(i1=1;i1<=n;i1++)//类似一维数组求最大和的方法,将一重循环改为三重循环for(i2=i1;i2<=n;i2++)for(j=1;j<=n;j++){res[i1][i2][j]=sum[i2][j]-sum[i1-1][j];//相当于一维数组中的第j 个数if(res[i1][i2][j-1]>0) res[i1][i2][j]+=res[i1][i2][j-1];if(res[i1][i2][j]>max) max=res[i1][i2][j];}cout<<max<<endl;}return 0;}例3(poj1458):求最长公共子序列的长度。
POJ 题目整理
初期:一.基本算法:(1)枚举. (poj1753,poj2965)(2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法.(4)递推.(5)构造法.(poj3295)(6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,poj2240)(3)最小生成树算法(prim,kruskal) (poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排) (poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,poj2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索 (poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)} (poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij} (最长公共子序列) (poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等) (poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487, poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题. (poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,poj2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解) (poj3155, poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446) (3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的).(poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点). (poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法. (poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法.(poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划. (poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj3336,poj3315,poj2148,poj1263) 以及补充Dp状态设计与方程总结1.不完全状态记录<1>青蛙过河问题<2>利用区间dp2.背包类问题<1> 0-1背包,经典问题<2>无限背包,经典问题<3>判定性背包问题<4>带附属关系的背包问题<5> + -1背包问题<6>双背包求最优值<7>构造三角形问题<8>带上下界限制的背包问题(012背包)3.线性的动态规划问题<1>积木游戏问题<2>决斗(判定性问题)<3>圆的最大多边形问题<4>统计单词个数问题<5>棋盘分割<6>日程安排问题<7>最小逼近问题(求出两数之比最接近某数/两数之和等于某数等等)<8>方块消除游戏(某区间可以连续消去求最大效益)<9>资源分配问题<10>数字三角形问题<11>漂亮的打印<12>邮局问题与构造答案<13>最高积木问题<14>两段连续和最大<15>2次幂和问题<16>N个数的最大M段子段和<17>交叉最大数问题4.判定性问题的dp(如判定整除、判定可达性等)<1>模K问题的dp<2>特殊的模K问题,求最大(最小)模K的数<3>变换数问题5.单调性优化的动态规划<1>1-SUM问题<2>2-SUM问题<3>序列划分问题(单调队列优化)6.剖分问题(多边形剖分/石子合并/圆的剖分/乘积最大)<1>凸多边形的三角剖分问题<2>乘积最大问题<3>多边形游戏(多边形边上是操作符,顶点有权值)<4>石子合并(N^3/N^2/NLogN各种优化)7.贪心的动态规划<1>最优装载问题<2>部分背包问题<3>乘船问题<4>贪心策略<5>双机调度问题Johnson算法8.状态dp<1>牛仔射击问题(博弈类)<2>哈密顿路径的状态dp<3>两支点天平平衡问题<4>一个有向图的最接近二部图9.树型dp<1>完美服务器问题(每个节点有3种状态)<2>小胖守皇宫问题<3>网络收费问题<4>树中漫游问题<5>树上的博弈<6>树的最大独立集问题<7>树的最大平衡值问题<8>构造树的最小环转一个搞ACM需要的掌握的算法.要注意,ACM的竞赛性强,因此自己应该和自己的实际应用联系起来.适合自己的才是好的,有的人不适合搞算法,喜欢系统架构,因此不要看到别人什么就眼红, 发挥自己的长处,这才是重要的.第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来.1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。
POJ_动态规划
题目:动态规划_2479 AC率:6120/20257题意解释:给定n个数,求两段连续不重叠子段的最大和。
比如1 -1 2 2 3 -3 4 -4 5 -5结果就是{2,2,3,-3,4} 和{5},也就是两者的和13。
选题原因:此题是对动态规划中的一个基础知识点求最大字段和的一个简单应用,难度不太大,比较具有代表性,是基础题型。
求最大字段和的方法有很多,但DP是最高效的,时间效率为O(n)。
有关求最大字段和的详细介绍参见王晓东《算法设计与分析》第三版59页相关部分。
这里仅附上求最大字段和的状态转移方程:b[j] = max {b[j-1] + a[j], a[j]}, 1 <= j <= n。
解题思路:先对数字串从左向右依次求出每段的连续子序列的最大字段和,并将其存入数组array[i]中(i为对应位置),再从右向左用同样的方法求一次最大字段和,并将每个子段i~n的和与对应的另一半1~i-1相加,求出最大值。
也就是对每个位置i来说,求出[1~i-1]的最大子段和以及[i~n]的最大子段和,再相加起来,求最大的一个就行了。
与基础的求最大字段和不同的是,该题需要对每个子段记录其最大和,即存入数组array[i]中。
程序代码:#include <stdio.h>int array[50001], num[50001];const int MIN = -999999999;int main(){int tcase, n;scanf("%d", &tcase);int tmp, ans, i, sum;while(tcase--){scanf("%d", &n);tmp = MIN; sum = 0;for(i = 1; i <= n; i++){scanf("%d", &num[i]);sum += num[i];if(sum > tmp)tmp = sum;array[i] = tmp; // 记录每个字段的最大值。
《动态规划》课件
xx年xx月xx日
• 动态规划概述 • 动态规划的基本概念 • 动态规划的求解方法 • 动态规划的应用实例 • 动态规划的优化技巧 • 动态规划的总结与展望
目录
01
动态规划概述
定义与特点
定义
动态规划是一种通过将原问题分解为 相互重叠的子问题,并存储子问题的 解以避免重复计算的方法。
特点
动态规划适用于具有重叠子问题和最 优子结构的问题,通过将问题分解为 子问题,可以找到最优解。
动态规划的适用范围
最优化问题
01
动态规划适用于解决最优化问题,如最大/最小化问题、决策问
题等。
子问题重叠
02
动态规划适用于子问题重叠的情况,即子问题之间存在共享状
态或参数。
递归关系
03
动态规划适用于具有递归关系的问题,可以通过递归方式求解
机器调度问题
总结词
动态规划可以应用于机器调度问题,以确定最优的调度方案,满足生产需求并降低成本 。
详细描述
机器调度问题是一个经典的优化问题,涉及到如何分配任务到机器上,以最小化成本或 最大化效率。通过动态规划,可以将机器调度问题分解为一系列子问题,如确定每个任 务的调度顺序、分配机器等,并逐个求解子问题的最优解,最终得到整个调度方案的最
VS
详细描述
记忆化搜索法是一种优化技术,通过存储 已解决的子问题的解,避免重复计算,提 高求解效率。这种方法适用于子问题数量 较少且相互独立的情况。
04
动态规划的应用实例
最短路径问题
总结词
通过动态规划解决最短路径问题,可以找到 从起点到终点的最短路径。
详细描述
在图论中,最短路径问题是一个经典的优化 问题,旨在找到从起点到终点之间的一条路 径,使得路径上的所有边的权重之和最小。 动态规划是一种有效的解决方法,通过将问 题分解为子问题并存储子问题的解,避免了 重复计算,提高了求解效率。
动态规划总结
动态规划总结动态规划系列内容算是结束了,虽然有关动态规划的知识点还有很多,但是我相信如果深刻掌握并理解了之前我们讲的内容,基本上leetcode 上面90% 以上的动态规划相关问题都可以很好解决。
动态规划就是利用历史记录,来避免我们的重复计算。
而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者二维数组来保存。
下面我们先来讲下做动态规划题很重要的三个步骤,第一步骤:定义数组元素的含义,上面说了,我们会用一个数组,来保存历史数组,假设用一维数组dp[] 吧。
这个时候有一个非常非常重要的点,就是规定你这个数组元素的含义,例如你的dp[i] 是代表什么意思?第二步骤:找出数组元素之间的关系式,我觉得动态规划,还是有一点类似于我们高中学习时的归纳法的,当我们要计算dp[n] 时,是可以利用dp[n-1],dp[n-2]…..dp[1],来推出dp[n] 的,也就是可以利用历史数据来推出新的元素值,所以我们要找出数组元素之间的关系式,例如dp[n] = dp[n-1] + dp[n-2],这个就是他们的关系式了。
而这一步,也是最难的一步,后面我会讲几种类型的题来说。
第三步骤:找出初始值。
学过数学归纳法的都知道,虽然我们知道了数组元素之间的关系式,例如dp[n] = dp[n-1] + dp[n-2],我们可以通过dp[n-1] 和dp[n-2] 来计算dp[n],但是,我们得知道初始值啊,例如一直推下去的话,会由dp[3] = dp[2] + dp[1]。
而dp[2] 和dp[1] 是不能再分解的了,所以我们必须要能够直接获得dp[2] 和dp[1] 的值,而这,就是所谓的初始值。
由了初始值,并且有了数组元素之间的关系式,那么我们就可以得到dp[n] 的值了,而dp[n] 的含义是由你来定义的,你想求什么,就定义它是什么,这样,这道题也就解出来了。
当然了,要想达到熟能生巧的程度,还是需要多加练习,多思考,多对比,多总结,不然的话,学到的东西很快就会忘记。
动态规划总结经典题目(经典中的经典)
动态规划总结——经典问题总结本文着重讨论状态是如何表示,以及方程是怎样表示的。
当然,还附上关键的,有可能作为模板的代码段。
但有的代码的实现是优化版的。
经典问题总结最长上升子序列(LIS)问题描述如下:设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>,其中k1<k2<…<km且aK1<ak2<…<akm。
求最大的m值。
这里采用的是逆向思维的方法,从最后一个开始想起,即先从A[N](A数组是存放数据的数组,下同)开始,则只有长度为1的子序列,到A[N-1]时就有两种情况,如果a[n-1] < a[n] 则存在长度为2的不下降子序列a[n-1],a[n];如果a[n-1] > a[n] 则存在长度为1的不下降子序列a[n-1]或者a[n]。
有了以上的思想,DP方程就呼之欲出了(这里是顺序推的,不是逆序的):DP[I]=MAX(1,DP[J]+1)J=0,1,...,I-1但这样的想法实现起来是)O(n^2)的。
本题还有更好的解法,就是O(n*logn)。
利用了长升子序列的性质来优化,以下是优化版的代码://最长不降子序const int SIZE=500001;int data[SIZE];int dp[SIZE];//返回值是最长不降子序列的最大长度,复杂度O(N*logN)int LCS(int n) { //N是DATA数组的长度,下标从1开始int len(1),low,high,mid,i;dp[1]=data[1];for(i=1;i<=n;++i) {low=1;high=len;while( low<=high ) { //二分mid=(low+high)/2;if( data[i]>dp[mid] ) {low=mid+1;}else {high=mid-1;}}dp[low]=data[i];if( low>len ) {++len;}}return len;}最长公共子序列(LCS)给出两个字符串a, b,求它们的最长、连续的公共字串。
动态规划(完整)ppt课件
3
• Ⅲ --Ⅳ :
B1—C1—T
4
• Ⅱ--Ⅲ--Ⅳ :A2—B1—C1—T
7
• Ⅰ--Ⅱ--Ⅲ --Ⅳ:
•
Q—A2—B1—C1—T
11
•
Q--A3—B1—C1—T
11
•
Q--A3—B2—C2—T
11
最新版整理ppt
3
最短路径
11
4
7
A1
4
2
6
11
47
3 2
Q
A2
4
B1
1
4 76
3
C1
3
B2 3
最新版整理ppt
16
(4)策略和允许策略集合
策略(Policy)也叫决策序列.策略有全过程 策略和 k 部子策略之分,全过程策略是指具 有n 个阶段的全部过程,由依次进行的 n 个 阶段决策构成的决策序列,简称策略,表示
为 p1,n{x1,x2, ,xn}。从 k 阶段到第 n 阶段,
依次进行的阶段决策构成的决策序列称为 k
新分支的创立。
最新版整理ppt
6
• 动态规划将复杂的多阶段决策问题分解为 一系列简单的、离散的单阶段决策问题, 采用顺序求解方法, 通过解一系列小问题 达到求解整个问题目的;
• 动态规划的各个决策阶段不但要考虑本阶 段的决策目标, 还要兼顾整个决策过程的 整体目标, 从而实现整体最优决策.
最新版整理ppt
第七章 动态规划
主要内容:
§7.1多阶段决策问题 §7.2 动态规划的基本概念和基本原理 §7.3 动态规划应用举例
最新版整理ppt
1
例 求解最短路问题
2
Q
4
动态规划总结
动态规划总结终于来到了设计思想中最难,也最有趣的这部分,在去年的google笔试中,7道算法设计题有2道动态规划(Dynamic Programming)。
看了这么久的算法,这部分也是唯⼀感觉到了⽐较难的地⽅,从这篇⽂章开始,将花连续的篇幅来讨论⼀些动态规划的问题。
这包括书上介绍过的计算⼆项式系数,Warshall算法求传递闭包,Floyd算法求完全最短路径,构造最有⼆叉查找树,背包问题和记忆功能。
也包括⼀些其他问题的解题报告(动态规划确实很难,对这⼀章的内容,我将搜索⼀些其他类型的问题来写解题报告,以真正的理解动态规划),例如矩阵连乘,最长公共⼦列,等等。
————————————————————————————————————————————————–1,什么是动态规划(DP)?⾮常重要!,不要认为概念不重要,理解的深刻,你才知道对于什么样的问题去考虑有没有动态规划的⽅法,以及如何去使⽤动态规划。
1)动态规划是运筹学中⽤于求解决策过程中的最优化数学⽅法。
当然,我们在这⾥关注的是作为⼀种算法设计技术,作为⼀种使⽤多阶段决策过程最优的通⽤⽅法。
它是应⽤数学中⽤于解决某类最优化问题的重要⼯具。
2)如果问题是由交叠的⼦问题所构成,我们就可以⽤动态规划技术来解决它,⼀般来说,这样的⼦问题出现在对给定问题求解的递推关系中,这个递推关系包含了相同问题的更⼩⼦问题的解。
动态规划法建议,与其对交叠⼦问题⼀次⼜⼀次的求解,不如把每个较⼩⼦问题只求解⼀次并把结果记录在表中(动态规划也是空间换时间的),这样就可以从表中得到原始问题的解。
关键词:它往往是解决最优化问题滴问题可以表现为多阶段决策(去⽹上查查什么是多阶段决策!)交叠⼦问题:什么是交叠⼦问题,最有⼦结构性质。
动态规划的思想是什么:记忆,空间换时间,不重复求解,由交叠⼦问题从较⼩问题解逐步决策,构造较⼤问题的解。
————————————————————————————————————————————————-关于斐波拉切数列可以作为最简单的⼀个例⼦来解释动态规划的思想,在前⾯讲斐波拉切数列时说过了,不再叙述。
POJ分类
模拟 76% 2005-5-6
1049 Microprocessor Simulation
模拟 73% 2005-5-6
1050 To the Max
DP 60% 2005-5-7
1051 P,MTHBGWB
55% 2005-5-7
1052 Plato's Blocks
1096 Space Station Shielding
送分题 45% 2005-5-1
1097 Roads Scholar
图论 63% 2005-5-1
1098 Robots
模拟 58% 2005-2-24
1099 Square Ice
送分题 65% 2005-5-5
1100 Dreisam Equations
75% 2005-5-2
1044 Date bugs
70% 2005-5-2
1045 Bode Plot
1046 Color Me Less
送分题 64% 2005-5-7
1047 Round and Round We Go
高精度 63% 2005-5-6
搜索 90% 2005-5-6
1101 The Game
搜索->BFS 74% 2005-5-6
1102 LC-Display
送分题 62% 2005-5-7
1103 Maze
模拟 64% 2005-5-6
1104 Robbery
递推 61% 2005-5-6
1105 S-Trees
1011 Sticks
Poj动态规划
[1]POJ 动态规划题目列表容易:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1208, 1276, 1322, 1414, 1456, 1458, 1609, 1644, 1664, 1690, 1699, 1740(博弈), 1742, 1887, 1926(马尔科夫矩阵,求平衡), 1936,1952, 1953, 1958, 1959, 1962, 1975, 1989, 2018, 2029,2039, 2063, 2081, 2082,2181, 2184, 2192, 2231, 2279, 2329, 2336, 2346, 2353,2355, 2356, 2385, 2392, 2424,不易:1019,1037, 1080, 1112, 1141, 1170, 1192, 1239, 1655, 1695, 1707,1733(区间减法加并查集), 1737, 1837, 1850, 1920(加强版汉罗塔), 1934(全部最长公共子序列), 1937(计算几何), 1964(最大矩形面积,O(n)算法), 2138, 2151, 2161(烦,没写), 2178,推荐:1015, 1635, 1636(挺好的), 1671, 1682, 1692(优化), 1704, 1717, 1722, 1726, 1732, 1770, 1821, 1853, 1949, 2019, 2127, 2176, 2228, 2287, 2342, 2374, 2378, 2384, 2411状态DP树DP构造最优解四边形不等式单调队列1015 Jury Compromise1029 False coin1036 Gangsters1037 A decorative fence1038 Bugs Integrated, Inc.1042 Gone Fishing1050 To the Max1062 昂贵的聘礼1074 Parallel Expectations1080 Human Gene Functions1088 滑雪1093 Formatting Text1112 Team Them Up!1141 Brackets Sequence1143 Number Game1157 LITTLE SHOP OF FLOWERS1159 Palindrome1160 Post Office1163 The Triangle1170 Shopping Offers1178 Camelot1179 Polygon1180 Batch Scheduling1185 炮兵阵地1187 陨石的秘密1189 钉子和小球1191 棋盘分割1192 最优连通子集1208 The Blocks Problem1239 Increasing Sequences1240 Pre-Post-erous!1276 Cash Machine1293 Duty Free Shop1322 Chocolate1323 Game Prediction1338 Ugly Numbers1390 Blocks1414 Life Line1432 Decoding Morse Sequences 1456 Supermarket1458 Common Subsequence1475 Pushing Boxes1485 Fast Food1505 Copying Books1513 Scheduling Lectures1579 Function Run Fun1609 Tiling Up Blocks1631 Bridging signals 2分+DP NLOGN 1633 Gladiators1635 Subway tree systems1636 Prison rearrangement1644 To Bet or Not To Bet1649 Market Place1651 Multiplication Puzzle1655 Balancing Act1661 Help Jimmy1664 放苹果1671 Rhyme Schemes1682 Clans on the Three Gorges 1690 (Your)((Term)((Project)))1691 Painting A Board1692 Crossed Matchings 1695 Magazine Delivery 1699 Best Sequence1704 Georgia and Bob1707 Sum of powers1712 Flying Stars1714 The Cave1717 Dominoes1718 River Crossing1722 SUBTRACT1726 Tango Tango Insurrection 1732 Phone numbers1733 Parity game1737 Connected Graph1740 A New Stone Game 1742 Coins P1745 Divisibility1770 Special Experiment 1771 Elevator Stopping Plan 1776 Task Sequences1821 Fence1837 Balance1848 Tree1850 Code1853 Cat1874 Trade on Verweggistan 1887 Testing the CATCHER 1889 Package Pricing1920 Towers of Hanoi1926 Pollution1934 Trip1936 All in All1937 Balanced Food1946 Cow Cycling1947 Rebuilding Roads1949 Chores1952 BUY LOW, BUY LOWER 1953 World Cup Noise1958 Strange Towers of Hanoi 1959 Darts1962 Corporative Network 1964 City Game1975 Median Weight Bead 1989 The Cow Lineup2018 Best Cow Fences2019 Cornfields2029 Get Many Persimmon Trees2033 Alphacode2039 To and Fro2047 Concert Hall Scheduling2063 Investment2081 Recaman's Sequence2082 Terrible Sets2084 Game of Connections2127 Greatest Common Increasing Subsequence 2138 Travel Games2151 Check the difficulty of problems2152 Fire2161 Chandelier2176 Folding2178 Heroes Of Might And Magic2181 Jumping Cows2184 Cow Exhibition2192 Zipper2193 Lenny's Lucky Lotto Lists2228 Naptime2231 Moo Volume2279 Mr. Young's Picture Permutations2287 TianJi -- The Horse Racing2288 Islands and Bridges2292 Optimal Keypad2329 Nearest number - 22336 Ferry Loading II2342 Anniversary party2346 Lucky tickets2353 Ministry2355 Railway tickets2356 Find a multiple2374 Fence Obstacle Course2378 Tree Cutting2384 Harder Sokoban Problem2385 Apple Catching2386 Lake Counting2392 Space Elevator2397 Spiderman2411 Mondriaan's Dream2414 Phylogenetic Trees Inherited2424 Flo's Restaurant2430 Lazy Cows2915 Zuma3017 Cut the Sequence3028 Shoot-out3124 The Bookcase3133 Manhattan Wiring3345 Bribing FIPA3375 Network Connection3420 Quad Tiling ?/?cat=5[2]动态规划方法总结1. 按状态类型分写在前面:从状态类型分,并不表示一题只从属于一类。
动态规划总结(基本类型)
动态规划总结(基本类型)JZM1. 0/1背包一个旅行者有一个最多能用m公斤的背包,现在有n件物品,它们的重量分别是W1,W2,...,Wn,它们的价值分别为C1,C2,...,Cn.若每种物品只有一件求旅行者能获得最大总价值。
分析:对于每个物品,只有装与不装的两种状态,那么我们可以在现在这种状态下枚举可以达到这种状态的所有可能,并求出最优解;我们设Value[I,W]表示前I的物品,质量不超过W时达到的最大价值,则对于每个物品(Wi,Ci)而言Value[I,W]=max{Value[I,W-Wi]+Ci,Value[I-1,W]};关键程序:for i:=1 to n(物品总数) dofor j:=m(背包的最大容量) to 1 doif j>=Wi(每个物品的质量) thenValue[I,J]=max{Value[I,J-Wi]+Ci,Value[I-1,J]} elseValue[I,J]=Value[I-1,J];2.完全背包一个旅行者有一个最多能用m公斤的背包,现在有n种物品每件的重量分别是W1,W2,...,Wn,每件的价值分别为C1,C2,...,Cn.若的每种物品的件数足够多.求旅行者能获得的最大总价值。
分析:本题是背包问题的另一中DP解法,写DP方程的重点是怎样把前一个状态表示成下一个状态;我们设F[I]为装了质量为I的物品所获得的最大价值,则对于每个物品(Wi,Ci)而言,装这个物品获得的最大价值就为F[I-Wi]+Ci,这样对每个物品都进行枚举,使最优数据不断迭代,从而达到最优解; F[I]=max{F[I-Wi]+Ci,F[I]};关键程序:for i:=m downto Wi doif F[i-Wi]+Ci>F[Wi] then F[Wi]:= F[i-Wi]+Ci;3.最长非降子序列设有由n个不相同的整数组成的数列,记为:a(1),a(2),……,a(n)且a(i)<>a(j) (i<>j)例如3,18,7,14,10,12,23,41,16,24。
动态规划部分知识点总结
动态规划部分知识点总结动态规划的基本思想动态规划的基本思想可以用“递推”来描述。
在解决一个问题时,通常需要先确定一个递推关系,然后利用递推关系逐步求解问题的最优解。
以求解最长递增子序列(Longest Increasing Subsequence,LIS)问题为例,最长递增子序列是指在一个无序的序列中找到一个最长的子序列,要求子序列中的元素是递增的。
假设原序列为A,最长递增子序列的长度为LIS(i),则可以通过递推关系来解决这个问题:LIS(i) = max(LIS(j)+1),其中j<i 且A[j]<A[i]通过这个递推关系,我们可以逐步求解出从A[1]到A[n]的最长递增子序列的长度,最终得到整个序列的最长递增子序列。
动态规划的特点动态规划有一些特点,可以帮助我们更好地理解和应用这种方法。
1. 重叠子问题:动态规划的关键特点之一是重叠子问题,即原问题可以分解为若干个子问题,不同的子问题可能有重叠的部分。
通过记录和利用子问题的解,可以避免重复计算,提高计算效率。
2. 最优子结构:动态规划适用于具有最优子结构性质的问题。
最优子结构指的是原问题的最优解可以通过子问题的最优解来求解。
换句话说,原问题的最优解可以由子问题的最优解推导出来。
3. 状态转移方程:动态规划问题通常可以通过状态转移方程来描述。
状态转移方程是指原问题与子问题之间的关系,它可以用数学公式或递推关系来表示。
通过状态转移方程,可以确定问题的递推规律,从而求解问题的最优解。
动态规划的应用动态规划广泛应用于各种领域,比如算法设计、优化问题、数据挖掘等。
它可以解决许多经典问题,比如最短路径、背包问题、编辑距离、最长公共子序列等。
1. 最短路径:最短路径问题是指在一个加权有向图或加权无向图中,找到一条从起点到终点的路径,使得路径上的边权重之和最小。
动态规划可以用于求解最短路径问题,比如利用Floyd-Warshall算法或Dijkstra算法,通过记录并利用子问题的解来求解最短路径。
python动态规划
python动态规划
动态规划(Dynamic Programming)是一种常见的算法设计方法,主要用于解决具有重叠子问题性质的问题。
它是一种自底向上的方法,通过将问题划分为相互依赖的子问题,从而简化问题的求解。
在动态规划中,最重要的是寻找问题的状态和状态转移方程。
状态即问题的子问题,状态之间的转移即问题的解决方法。
以求解斐波那契数列为例,斐波那契数列的定义是:
F(n)=F(n-1)+F(n-2),其中F(0)=0,F(1)=1。
我们可以使用动态规划来求解斐波那契数列。
首先定义状态,我们可以将F(n)作为一个状态,而F(n-1)和
F(n-2)作为子状态。
那么问题的状态转移方程可以表示为:F(n) = F(n-1) + F(n-2)。
接下来,我们需要确定问题的初始状态和边界条件。
对于斐波那契数列来说,初始状态可以是F(0)和F(1),边界条件为n的取值范围。
然后,我们可以使用一个数组来存储每个状态的值,通过自底向上的方式,逐步计算子问题的解,最终求得问题的解。
动态规划具有很多优势,通过将问题划分为子问题,可以避免重复计算,提高算法的效率。
同时,动态规划还可以降低问题的时间复杂度,提高算法的可行性。
除了斐波那契数列,还有很多其他问题可以使用动态规划来解决,比如背包问题、最长公共子序列等。
总结起来,动态规划是一种解决具有重叠子问题性质的问题的算法设计方法。
通过将问题划分为相互依赖的子问题,利用自底向上的方式,逐步计算子问题的解,求得问题的最优解。
动态规划具有高效性和可行性等优点,是一种常见的求解问题的方法。
php算法学习之动态规划
php算法学习之动态规划
动态规划程序设计是对解最优化问题的一种途径、一种方法,最终问题的最优解可以通过前面子问题的最优解推导出来。
下面为大家了php算法学习之动态规划,希望能帮到大家!
对于动态规划这个算法,自己学习的还不是很透彻,简单的总结自己学习的感受是:
动态规划思想中融合了递归和分治的思想,但不同于分治的是,动态规划求解中会通过状态记录求解过程中每一个分支的最优解法,以此节省了许多分支的重复计算。
动态规划最重要同样也是最难的两步是找到描述子问题的状态以及状态间的推导关系。
比较可能使用动态规划的问题:求最大最小值、是否有可行方案以及可行方案个数。
先来一个最常见的题体验一下,求斐波那契数列(不知道的同学请自行百度一下)某个位置的值?
应用分治法求解代码
分治求解过程中,会有许多重复的运算,如下图3和2都被重复运算了两次,index值越大重复计算的次数就越多。
ok,下面我们看一下动态规划如何进行优化。
我们定义了一个数组来记录斐波那契每个位置的值,这就相当于我们定义了一个状态;每个位置的值等于它前面两个的加和,这就相当于一个状态转移方程。
这里通过数组记录状态就是一种以空间换时间的思想,其实和我们平时开发用到的缓存的设计很像。
总结动态规划求解可以分为4步:
1、确定要解决的子问题,即状态的定义。
2、列出状态转移方程。
3、根据给定条件,初始化已知状态值。
4、求解最终问题解。
下面再来解一道比较有意思的问题,爬楼梯:
你正在爬楼梯,需要n步你才能到达顶部。
但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部?。
动态规划算法(java)
动态规划算法(java)⼀、动态规划算法 众所周知,递归算法时间复杂度很⾼为(2^n),⽽动态规划算法也能够解决此类问题,动态规划的算法的时间复杂度为(n^2)。
动态规划算法是以空间置换时间的解决⽅式,⼀开始理解起来可能⽐较困难,⾃⼰画画也许明⽩了很多。
⼆、动态规划算法分析先举个例⼦:{7,0,0,0,0},{3,8,0,0,0},{8,1,0,0,0},{2,7,4,4,0},{4,5,2,6,5} 这个⼆维数组,求⼀下,顶层到底层,只能通过两端来相加的最⼤值(也就是说这棵树的最长路径)。
分析:(1)第⼀步:有底层向上层算起,因为这是⼀个⾦字塔的形状,底层向上算起,就可以最终到⼀个值,这个值就是最⼤值,(2)每⼀层相加,然后⽐较取最⼤数。
即:三、代码实现@Testpublic void test2(){int[][] arr={{7,0,0,0,0},{3,8,0,0,0},{8,1,0,0,0},{2,7,4,4,0},{4,5,2,6,5}};int max = maxSumNew(arr,5);System.out.println(max);}/*** 动态规划* @param arr* @param n* @param* @return*/public int maxSumNew(int arr[][],int n){if(arr==null){return 0;}int[][] max = new int[n][n];for(int i = n-1; i >=0; i--){for(int j = 0; j <= i; j++){if(i==n-1){max[n-1][j] = arr[n-1][j];}else{max[i][j] = Math.max(max[i+1][j],max[i+1][j+1]) + arr[i][j];}}}return max[0][0];}以上是⼩弟的总结,如果有不正确的地⽅,还请⼤⽜指正。
动态规划总结
区别:
动态规划
全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解。
如果用贪心算,就是我每一次拿那张可能拿的最大的。
比如16,我第一次拿20拿不起,拿10元,OK,剩下6元,再拿个5元,剩下1元
也就是3张 10、5、1。
每次拿能拿的最大的,就是贪心。
但是一定注意,贪心得到的并不是最优解,也就是说用贪心不一定是拿的最少的张数
再从这些最优解中获取更优的答案
典型的例子数塔问题
画个图就能看出来
-----------------------------------------------------------------
动态规划和贪心算法的区别
动态规划和贪心算法都是一种递推算法
均有局部最优解来推导全局最优解
不同点:
贪心算法:
1.贪心算法中,作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一部之前的最优解则不作保留。
2.由(1)中的介绍,可以知道贪心法正确的条件是:每一步的最优解一定包含上一步的最优解。
动态规划算法:
1.全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解
贪心算法是种策略,思想。。。
它并没有固定的模式
比如最简单的背包问题
用贪心的思想去做,就可能有很多种方法
性价比最高的、价值最高的、重量最轻的
java 动态规划
java 动态规划动态规划(Dynamic Programming)是一种算法设计技巧,用于解决具有重叠子问题和最优子结构的问题。
它通过将问题分解成更小的子问题,并利用子问题的解构建原问题的解,从而避免重复计算。
动态规划的核心思想是将问题划分成多个阶段,每个阶段都需要根据前一阶段的结果做出决策。
通过记忆化搜索,即将计算过的结果存储起来,在需要的时候直接取用,避免重复计算。
动态规划问题通常具有以下特点:1. 最优子结构:问题的最优解中包含了子问题的最优解。
2. 重叠子问题:子问题之间存在重叠,即多次计算相同的子问题。
3. 子问题独立:子问题之间不存在关联。
动态规划的解决过程一般分为以下步骤:1. 确定问题的阶段:将问题划分成多个阶段,每个阶段需要根据前一阶段的结果进行决策。
2. 确定状态:确定每个阶段的状态,即问题的可变参数。
3. 确定状态转移方程:确定问题的状态转移方程,即当前阶段的状态如何由前一阶段的状态转换而来。
4. 确定初始条件和边界条件:确定问题的初始状态和边界状态。
5. 通过状态转移方程,自底向上地求解问题。
动态规划可以解决很多实际问题,例如最长公共子序列、最大子数组和、背包问题等。
以最长公共子序列(Longest Common Subsequence)为例,假设有两个字符串s1和s2,求它们的最长公共子序列的长度。
首先,我们将问题划分成多个阶段,每个阶段对应两个字符串的子串,从头到尾依次遍历两个字符串的字符。
然后,我们确定状态为dp[i][j],表示字符串s1的前i个字符和字符串s2的前j个字符的最长公共子序列的长度。
接下来,我们确定状态转移方程:如果s1[i] == s2[j],则dp[i][j] = dp[i-1][j-1] + 1;即将两个字符串的当前字符加入最长公共子序列。
如果s1[i] != s2[j],则dp[i][j] = max(dp[i-1][j], dp[i][j-1]);即将两个字符串的当前字符分别加入,取最长的作为最长公共子序列。
动态规划 java
动态规划 java动态规划(Dynamic Programming)是一种通过将问题分解成子问题并记录子问题的解来解决复杂问题的方法。
它通常用于求解优化问题,如求最优解或最大化/最小化某个目标函数的值。
动态规划的核心思想是利用已计算出的子问题的解来求解当前问题。
通过自底向上地计算子问题的解,并将其保存在一个表格中,可以避免重复计算,从而提高计算效率。
动态规划的步骤如下:1. 确定问题的状态:将问题划分为若干个子问题,并定义状态变量表示子问题的解。
通常,状态变量与问题的输入有关。
2. 定义状态转移方程:利用已计算出的子问题的解来求解当前问题的解。
根据问题的性质,可以通过递归或迭代的方式定义状态转移方程。
3. 初始化边界条件:初始化状态变量的初始值,以便开始通过状态转移方程计算。
4. 计算问题的解:根据问题的状态转移方程,通过自底向上的方式计算子问题的解,并保存在表格中。
5. 返回问题的解:根据表格中保存的子问题的解,返回问题的最终解。
下面以计算斐波那契数列为例,展示动态规划的实现过程。
```javapublic class Fibonacci {public static int fibonacci(int n) {if (n <= 1) {return n;}int[] dp = new int[n + 1];dp[1] = 1;for (int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}public static void main(String[] args) {int n = 10;int result = fibonacci(n);System.out.println("Fibonacci(" + n + ") = " + result);}}```在这个例子中,我们使用动态规划的思想计算斐波那契数列的第n个数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
例1:求一维数组中连续数之和的最大值。
代码:#include<iostream>using namespace std;int a[100];//记录一维数组int res[100];//res[i]表示以第i个数为末尾的连续数之和的最大值int main(){int i,n,max;while(1){cin>>n;if(!n) break;memset(res,0,sizeof(a)),max=-1270000;for(i=0;i<n;i++){cin>>a[i];res[i]=a[i];if(i>0 && res[i-1]>0) res[i]+=res[i-1];//动态规划法if(res[i]>max) max=res[i];//打擂法}cout<<max<<endl;}return 0;}例2(poj1050):求二维数组中子矩阵之和的最大值。
(例1的拓展)代码:#include<iostream>using namespace std;int a[101][101];//记录二维数组int sum[101][101];//sum[i][j]表示第j列前i行的数之和int res[101][101][101];//res[i1][i2][j]表示从第i1行到第i2行,以第j个数为末尾的连续数之和的最大值int main(){int i,i1,i2,j,n,temp,max;while(1){cin>>n;if(!n) break;memset(sum,0,sizeof(sum)),memset(res,0,sizeof(res));for(i=1;i<=n;i++)for(j=1;j<=n;j++){cin>>a[i][j];//输入二维数组sum[i][j]=sum[i-1][j]+a[i][j];//求第j列前i行之和}max=-1270000;for(i1=1;i1<=n;i1++)//类似一维数组求最大和的方法,将一重循环改为三重循环for(i2=i1;i2<=n;i2++)for(j=1;j<=n;j++){res[i1][i2][j]=sum[i2][j]-sum[i1-1][j];//相当于一维数组中的第j 个数if(res[i1][i2][j-1]>0) res[i1][i2][j]+=res[i1][i2][j-1];if(res[i1][i2][j]>max) max=res[i1][i2][j];}cout<<max<<endl;}return 0;}例3(poj1458):求最长公共子序列的长度。
代码:#include<iostream>#include<string>using namespace std;int res[500][500];//res[i][j]表示s1中第i个字符、s2中第j个字符之前的最长公共子序列长度int max(int a,int b){return a>b?a:b;}int main(){int i,j,n1,n2;string s1,s2;while(1){cin>>s1>>s2;memset(res,0,sizeof(res)),n1=s1.length(),n2=s2.length();for(i=0;i<n1;i++)for(j=0;j<n2;j++){if(s1[i]==s2[j]) res[i+1][j+1]=res[i][j]+1;//动态规划法else res[i+1][j+1]=max(res[i][j+1],res[i+1][j]);}cout<<res[n1][n2]<<endl;}return 0;}例4(poj1163):求三角形内可取得的最大和。
#include<iostream>using namespace std;int a[101][101];int res[101][101];//res[i][j]表示从顶端到达位置(i,j)所取得的最大值int Max(int a,int b){return a>b?a:b;}int main(){int i,j,n,max;cin>>n;while(n){for(i=0;i<n;i++)//输入数据for(j=0;j<=i;j++)cin>>a[i][j];res[0][0]=a[0][0];for(i=1;i<n;i++) res[i][0]=res[i-1][0]+a[i][0];//求解边界情况for(i=1;i<n;i++) res[i][i]=res[i-1][i-1]+a[i][i];for(i=2;i<n;i++)//求解一般情况for(j=1;j<i;j++)res[i][j]=Max(res[i-1][j],res[i-1][j-1])+a[i][j];//动态规划max=res[n-1][0];for(j=1;j<n;j++)if(res[n-1][j]>max) max=res[n-1][j];cout<<max<<endl;cin>>n;}return 0;}例5(poj1157):固定标号顺序的插花问题。
代码:#include<iostream>using namespace std;int a[101][101];int res[101][101];//res[i][j]表示前i朵花放在前j个花瓶中所产生的最大价值int max(int a,int b){return a>b?a:b;}int main(){int i,j,f,v;cin>>f>>v;for(i=1;i<=f;i++)for(j=1;j<=v;j++)cin>>a[i][j];res[1][1]=a[1][1];//求解边界情况for(j=2;j<=v;j++){res[1][j]=res[1][j-1];if(a[1][j]>res[1][j]) res[1][j]=a[1][j];//求解一朵花的情况res[j][j]=res[j-1][j-1]+a[j][j];//求解j个花瓶j朵花的情况}for(i=2;i<=f;i++)//求解其他情况f or(j=i+1;j<=v;j++)res[i][j]=max(res[i][j-1],res[i-1][j-1]+a[i][j]);//动态规划cout<<res[f][v]<<endl;return 0;}例6(poj1125):实际上就是利用Floyd算法求任意顶点对之间的最短路径,只不过要做一下变形而已。
代码:#include<iostream>using namespace std;const int INFINITY=1000000;int a[101][101];//Floyd算法均用邻接矩阵表示图int main(){int i,j,k,n,m,imin,min,max[101];cin>>n;while(n){for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(i==j) a[i][j]=0;else a[i][j]=INFINITY;//初始化for(i=1;i<=n;i++){cin>>m;for(j=1;j<=m;j++)cin>>k,cin>>a[i][k];//输入数据}for(k=1;k<=n;k++)//Floyd算法动态规划for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(a[i][k]+a[k][j]<a[i][j]) a[i][j]=a[i][k]+a[k][j];for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(a[i][j]>max[i])max[i]=a[i][j];//求从i出发到其他顶点的最短距离的最大值min=INFINITY;for(i=1;i<=n;i++)if(max[i]<min) imin=i,min=max[i];//在各顶点中求最小值if(min>=INFINITY) cout<<"disjoint"<<endl;else cout<<imin<<' '<<min<<endl;cin>>n;}return 0;}例7(poj1178):在国王与骑士汇合的所有路径中,求最短路径的长度。
(先将数组降维预处理,再用Floyd动态规划法求解)#include<iostream>#include<string>using namespace std;const int INFINITY=10000;int a[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};//王的8种走法int b[8][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}};//马的8种走法int king[64][64];//king[i][j]表示王从位置i到j的最少步数int knight[64][64];//knight[i][j]表示马从位置i到j的最少步数int min(int a,int b){return a<b?a:b;}void init(){int i,j,k;for(i=0;i<64;i++){//初始化for(j=0;j<64;j++)if(i==j) king[i][j]=knight[i][j]=0;else king[i][j]=knight[i][j]=INFINITY;}for(i=0;i<8;i++)//降维的预处理for(j=0;j<8;j++)for(k=0;k<8;k++){if(i+a[k][0]>=0&&i+a[k][0]<=7&&j+a[k][1]>=0&&j+a[k][1]<=7)king[i*8+j][(i+a[k][0])*8+(j+a[k][1])]=1;if(i+b[k][0]>=0&&i+b[k][0]<=7&&j+b[k][1]>=0&&j+b[k][1]<=7)knight[i*8+j][(i+b[k][0])*8+(j+b[k][1])]=1;}}void dp(){int i,j,v;for(v=0;v<64;v++)for(i=0;i<64;i++)for(j=0;j<64;j++){if(king[i][v]+king[v][j]<king[i][j]) king[i][j]=king[i][v]+king[v][j];if(knight[i][v]+knight[v][j]<knight[i][j])knight[i][j]=knight[i][v]+knight[v][j];}}int main(){int i,j,k,sum,res=INFINITY,temp1,temp2;int knight_num,king_pos,knight_pos[63];string str;cin>>str;init();//预处理dp();//Floyd动态规划法knight_num=str.length()/2-1;//马的数量if(knight_num==0) cout<<'0'<<endl,exit(1);king_pos=(str[0]-'A')*8+(str[1]-'1');//王的位置for(i=0;i<knight_num;i++) knight_pos[i]=(str[2*i+2]-'A')*8+(str[2*i+3]-'1');//马的位置for(i=0;i<64;i++){//最终汇合到位置isum=0;for(j=0;j<knight_num;j++) sum+=knight[knight_pos[j]][i];//马走的总步数for(j=0;j<64;j++){//王走到位置j与马汇合temp1=king[king_pos][j];//加上王走的步数temp2=INFINITY;for(k=0;k<knight_num;k++)temp2=min(temp2,knight[knight_pos[k]][j]+knight[j][i]-knight[knight_pos[k]][i]);//特殊处理运载王的马res=min(res,sum+temp1+temp2);}}cout<<res<<endl;return 0;}【小结】关于动态规划的问题,分为两大类:(1)最优子结构——递推求解:分析问题,将其分解为若干个子问题,确定子问题的状态及其状态转移方程,利用子问题的解求原问题的解;(2)重叠子问题——递归求解(记忆化搜索):避免重复求解子问题的一种优化方法。