如何识别动态规划的题目:
1.提出的问题具有最优子结构性质(每一步子问题最优,导致最后得到最优解)
2.无后效性(状态确定后,此后的值只和该状态有关。和达成的手段,路径无关)
如何解决动态规划的题目:
1.对原问题进行分析,将原问题划分成若干子问题,一步一步来。
2.确定每个子问题的状态。
3.从题干中确定一些初始状态(边界状态)的值
4.通过子问题,确认状态转移方程(从已知的出未知的方程)
动态规划经典例题:
解法一(递归+动态规划)--->由于递归会导致重复运算,所以把运算过的解都存在数组中,直接调用。节省时间
1 /* 2 求三角形顶点到底边的最大值 3 可选择的路为正下方和右斜下方 4 例:n=4 5 7 6 6 8 7 2 1 3 8 5 7 6 8 9 输出: 26 10 题解:数字三角形的记忆递归型动归程序 11 由于用递归计算的话,需要重复计算很多数据,太耗时间 12 所以将计算过一次的数据存在m数组中,就可以避免重复的计算 13 */ 14 15 #include<iostream> 16 #include<algorithm> 17 using namespace std; 18 #define MAX 101 19 int a[MAX][MAX];//三角形数组 20 int m[MAX][MAX];//存放指定顶点到底边的最大距离 21 int n;//三角形的阶 22 23 int maxsum(int x,int y) 24 { 25 if(m[x][y]!=-1) 26 return m[x][y];//最大值已经给了,可以不用计算 27 if(x==n)//到底了 28 m[x][y]=a[x][y]; 29 else 30 { 31 int i = maxsum(x+1,y);//找出下面那个数的最大值 32 int j = maxsum(x+1,y+1);//找出右下角那个数的最大值 33 m[x][y] = max(i,j)+a[x][y]; 34 35 } 36 return m[x][y]; 37 } 38 39 40 int main() 41 { 42 int i; 43 int j; 44 cout<<"请输入三角形的阶"<<endl; 45 cin>>n; 46 cout<<"请输入三角形的具体数据"<<endl; 47 for(i=1;i<=n;i++) 48 for(j=1;j<=i;j++) 49 { 50 cin>>a[i][j];//具体数据 51 m[i][j]=-1; //初始化 52 } 53 cout<<maxsum(1,1)<<endl; 54 55 56 57 58 59 return 0; 60 }
解法二 (递推+动态规划)-->用递推的方法,从最后一行推起,由已知推出未知
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 #define Max 101 6 int main() 7 { 8 int a[Max][Max];//三角形数组 9 int n,i,j; 10 int sum[Max][Max]; 11 cout<<"请输入三角形的阶"<<endl; 12 cin>>n; 13 cout<<"请输入具体数据"<<endl; 14 for(i=1;i<=n;i++) 15 for(j=1;j<=i;j++) 16 cin>>a[i][j]; 17 //初始化 18 for(j=1;j<=n;j++) 19 sum[n][j]=a[n][j]; 20 //通过递推的方法,一步一步往上加 21 for(i=n-1;i>=1;i--) 22 for(j=1;j<=i;j++) 23 { 24 sum[i][j]=max(sum[i+1][j],sum[i+1][j+1])+a[i][j]; 25 } 26 27 cout<<sum[1][1]<<endl; 28 29 30 return 0; 31 }