实验四动态规划算法设计与应用
一. 实验目的和要求
1.加深对动态规划算法的基本原理的理解,掌握用动态规划方法求解最优化问题的方法步骤及应用;
2.用动态规划设计整数序列的最长递增子序列问题的算法,分析其复杂性,并实现;
3.用动态规划设计求凸多边形的三角剖分问题的算法,分析其复杂性,并实现。
4.选做题:用动态规划设计求解0/1背包问题的算法,分析其复杂性,并实现。
二.基本原理
动态规划是一种非常重要的程序设计方法,常用于求解最优化问题。最优化问题:给定若干个约束条件和一个目标函数,在某指定集合中求满足所有约束条件的且使得目标函数值达最大或最小的元素和相应的目标函数值,即:问题的最优值和最优解。
适用动态规划求解的问题的基本要素:
(1)满足最优性原理:即一个最优化问题的最优解包含了其子问题的最优解。
(2)无后向性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也即,某状态以后的过程不会影响以前的状态,只与当前状态有关,这种特性也被称为无后效性。
(2)具有重叠的子问题:即问题被分解成的子问题存在互相重叠。动态规划方法对于这些重叠的子问题只求解一次,以提高算法的效率。
三.该类算法设计与实现的要点
动态规划算法求解最优化问题的步骤:
(1) 找出问题的最优子结构。分析问题的最优解(最优值)的结构特征。
(2) 递归地定义最优值。根据最优子结构,确定最优值所满足的递归公式。
(3) 计算最优值。根据最优值的递归公式,采用自底向上的迭代或自顶向下的递归,计算最优值。
(4) 构造最优解。在求解最优值的过程中要记录下得到最优值的相应最优解的信息,并根据该信息构造最优解。
注意:在计算最优值时应保存相应的信息:
(a) 已经求出的子问题的最优值(避免重复计算)。
(b) 最优解的有关信息。
动态规划算法求解其它问题的步骤:
(1) 根据最优化原理分析问题的解的结构。
(2) 递归地定义问题的解。
(3) 计算问题的解。根据解的递归公式,自底向上或自顶向下地计算解,计算过程中注意保存已经求出的子问题的解。
其中,自底向上方法通过迭代来实现,适用于所有的子问题都需要解的情况,实现时要注意根据递归公式正确确定子问题的求解顺序。自顶向下方法通过递归来实现,适用于不必解所有的子问题的情况,实现时要注意标记子问题是否计算过,同一个子问题只在第一次递归调用时计算并存储结果。
四.实验内容
(一) 最长递增子序列问题
1.问题描述
求一个由n个整数组成的整数序列的最长递增子序列。一个整数序列的递增子序列可以是序列中非连续的数按照原序列顺序排列而成的。最长递增子序列是其递增子序列中长度最长的。
2. 具体要求(若在ACM平台上提交程序,必须按此要求)――平台上1700题
输入:输入的第一行是一个正整数n,表示测试例个数。接下来几行是n个测试例的数据,每个测试例的数据由两行组成,其中第一行为一个正整数k (k<=500),表示整数序列的长度,第二行给出整数序列,整数之间用一个空格隔开。(设给出的每个整数序列的最长递增子序列都是唯一的。)
输出:对于每个测试例输出两行,第一行为最长递增子序列的长度,第二行为最长递增子序列,整数之间用一个空格隔开。两个测试例的输出数据之间用一个空行隔开,最后一个测试例后无空行。
3代码如下:
#include
#define MAX 50
void bubble(int r[],int n,int B[])
{
int i,j,temp;
for(i=0;i { for(j=0;j if(r[j]>r[j+1]) { temp=r[j]; r[j]=r[j+1]; r[j+1]=temp; } } for(i=0;i { B[i]=r[i]; } } void Lcss(int H[MAX][MAX],int n,int A[MAX],int L,int B[MAX]) { int i=n,j=n,k=L,C[MAX]; while(i>0&&j>0) { if(H[i][j]==0) { C[k--]=A[i]; i=i-1; j=j-1; } else if(H[i][j]==1) i=i-1; else j=j-1; C[0]=B[0]; }