算法设计与分析——动态规划

动态规划算法通常用于求解具有最优性质的问题。

基本思想:将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题中得到原问题的解。(适合用于动态规划求解的问题,经分解得到的子问题往往不是相互独立的。若用分治方法解决,则得到的子问题的数目太多,某些子问题会被重复计算)若我们保存已解决的子问题答案,在需要的时候再找出以求得的答案,可以避免大量重复计算,节省时间。

动态规划有效性依赖于问题本身的两个重要性质:
1、最优子结构:问题最优解包含了妻子问题的最优解。
2、重叠子问题:在用递归算法自顶向下解问题时,每次产生的子问题并不总是新问题,有些字问题被反复计算多次。动态规划正是用了这种问题的重叠性质,对每一个子问题只解一次,而后将其保存在一个表格中,在以后能尽可能多的利用这些子问题的解。

例题一:
最长公共子序列
算法设计与分析——动态规划
算法设计与分析——动态规划

#define num=100;
int c[num][num];
int d[num][num];
void lendth(int m,int n,const char x[],char y[])
{
int i,j;
for(i=1;i<=m;++i)
c[i][0]=0;
for(i=1;i<=n;++i)
c[0][i]=0;
for(i=1;i<=m;++i)
for(j=1;j<=n;++j)
{
if(x[i]==y[i])
{
c[i][j]=c[i-1][j-1]+1;
d[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
}
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
算法设计与分析——动态规划
例题二:
最大子段和
算法设计与分析——动态规划
算法设计与分析——动态规划

动态递归式:
b[j]=max{b[j-1]+a[j],a[j]},1<=j<=n;

#define num 1001;
int a[num];
int sum(int n,int &besti,int &bestj)
{
int sum=0;
int b=0;
int begin=0;
for(int i=1;i<=n;++i)
{
if(b>0)
b+=a[i];
else
{
b=a[i];
begin=i;
}
if(b>sum)//得到新的最优解,更新
{
sum=b;
besti=begin;
bestj=i;
}
}
}
return sum;
}

动态规划最主要的方式是找到相应的动态递归式,就例如例题二中的
b[j]=max{b[j-1]+a[j],a[j]},1<=j<=n;