1、对动态规划的理解
能用动态规划解决的问题有两大特性:最优子结构特性、重叠子问题特性
最优子结构即:要求原问题的最优解,必先求子问题的最优解
重叠子问题即:在求各个子问题的最优解时会出现重复计算的情况
用动态规划解题的步骤:
1)分析最优子结构
2)建立递归关系,列出递归方程
3)计算最优值
4)构造最优解
这四个步骤列出来好像很简单,但是我觉得实际应用起来还是有难度的,特别是列出递归方程这一步,需要去分析子问题和原问题之间的关系,另外列出了递归方程之后还要寻求适当的数据结构进行编程,对于数据结构表示的具体意义也要比较清楚,还有一些特殊位置的初值也至关重要。通过这几周对于动态规划的学习,其实,坦白说,我觉得它还是挺难的,我上课的时候能基本理解老师讲的思想,但是真正实践起来还是会不知道从何下手。所以我决定先把课本的例子弄懂,于是在经过自己动手敲出【矩阵连乘】的代码还有跟同学讲解整个代码的过程之后,我发现对动态规划有了进一步深入的理解,这次的经历也让我学到:当你觉得你好像理解不了代码的时候,不要自己闷头在那里想,尝试着跟其他同学讲一下代码,在讲的过程中你的思路也就越来越清晰,把她讲懂了,自己也就懂了。
#图为跟同学讲代码的过程
2、编程题1、2的递归方程
最长单调子序列长度
递归方程:b[i]=max(b[j]+1,b[i])[j<i&&a[j]<a[i]];
源代码:
1 #include<iostream> 2 using namespace std; 3 int main(){ 4 int n; 5 cin>>n; 6 int a[n];//记录原始数据 7 int b[n];//记录第0个元素到当前元素的最长递增序列的长度 8 for(int i=0;i<n;i++){ 9 cin>>a[i]; 10 b[i]=1;//初值均为1 11 } 12 for(int i=1;i<n;i++) {//当前元素 13 for(int j=0;j<i;j++){//当前元素之前的元素 14 if(a[j]<a[i]&&b[j]+1>b[i])//如果当前元素之前的元素比当前元素小并且当前元素的最长加一比当前元素最长大 15 b[i]=b[j]+1; 16 } 17 } 18 int max=1; 19 for(int i=0;i<n;i++){ 20 if(b[i]>max) 21 max=b[i]; 22 } 23 cout<<max; 24 return 0; 25 }
租用游艇问题
递归方程:a[i][j]=max(a[i,k]+a[k][j])[i<=k<j];
源代码:
1 #include<iostream> 2 using namespace std; 3 int rent(int a[][101],int n){ 4 int i,j; 5 for(int i=1;i<=n;i++){ 6 a[i][i]=0; 7 } 8 for(int r=2;r<=n;r++){ 9 for(i=1;i<=n-r+1;i++){ 10 j=i+r-1; 11 for(int k=i+1;k<j;k++){ 12 int t=a[i][k]+a[k][j]; 13 if(t<a[i][j]){ 14 a[i][j]=t; 15 } 16 } 17 } 18 } 19 return a[1][n]; 20 } 21 int main(){ 22 int n; 23 cin>>n; 24 int a[101][101]; 25 for(int i=1;i<n;i++){ 26 for(int j=i+1;j<=n;j++){ 27 cin>>a[i][j]; 28 } 29 } 30 cout<<rent(a,n); 31 return 0; 32 }
3、结对编程情况汇报
感觉我和队友对于动态规划都不是很理解,所以一开始做题的时候我们还是习惯性用之前的思维去想问题,结果打出来的代码就会出问题,所以我们最终决定先分别去认真看一下书,理解一下动态规划之后再来做题,感觉效果就好了很多,通过这次经历我也懂得以后做题莫要急于求成,先把基础的东西搞清楚再做题,不然只会浪费对方的时间,一起做题也很没有效率。
原文:https://www.cnblogs.com/huangroumin/p/9939876.html