动态规划可以用递归实现,用递归实现会比较简单,就是找递归出口比较难,能找到递归的规律,那用循环就肯定能做了,dp和贪心算法还是有区别的,用递归有可能会重复算一个数,斐波那契就是一个例子,循环会把它记录下来,所以复杂度会比较小。
一:理解dp

就是选最大的数是多少,但是同一时间不能选;
二:简单题理解
就是选出和最大的数是多少,但是相邻的不能选,dp是从后往前分析,找出规律,然后写递归出口,转换成数组,
递归代码:
#include<bits/stdc++.h> using namespace std; int rec_opt(int arr[],int len) { if(len==0) return arr[0]; else if(len==1) return max(arr[0],arr[1]); else { int a=rec_opt(arr,len-1);//注意传参数的时候和主函数一样,len是控制下标 int b=rec_opt(arr,len-2)+arr[len]; return max(a,b); } } int main() { int arr[7]={1,2,4,1,7,8,3}; cout<<rec_opt(arr,6)<<endl;//求的是下标为六前的和为最大值的数 return 0; } 数组实现:
#include<bits/stdc++.h> using namespace std; int main() { int arr[7]={1,2,4,1,7,8,3}; for(int i=0;i<7;i++) { if(i==0) arr[i]=arr[i]; if(i==1) arr[i]=max(arr[i],arr[i-1]); if(i>1) arr[i]=max(arr[i-2]+arr[i],arr[i-1]); } cout<<arr[6]<<endl; return 0; } 三:题目实现:



递归实现:
#include<bits/stdc++.h> using namespace std; int rec_opt(int arr[],int len,int s) { if(s==0) return true; else if(len==0) return arr[0]==s; else if(arr[len]>s) return rec_opt(arr,len-1,s); else { //int a=rec_opt(arr,len-1,s-arr[len]) //int b=ec_opt(arr,len-1,s) return (rec_opt(arr,len-1,s-arr[len])||rec_opt(arr,len-1,s)); } } int main() { int arr[6]={3,34,4,12,5,2}; cout<<rec_opt(arr,5,9)<<endl; cout<<rec_opt(arr,5,10)<<endl; cout<<rec_opt(arr,5,11)<<endl; cout<<rec_opt(arr,5,13)<<endl; return 0; } 数组实现:
#include<bits/stdc++.h> using namespace std; int main() { int arr[6]={3,34,4,12,5,2}; int dp[6][14]; memset(dp,0,sizeof(dp)); for(int i=0;i<6;i++) { for(int j=0;j<14;j++) { if(j==0) dp[i][j]=1; else if(i==0) { if(arr[i]==j) dp[i][j]=1; else dp[i][j]=0; } else if(arr[i]>j) dp[i][j]=dp[i-1][j]; else { int a=dp[i-1][j]; int b=dp[i-1][j-arr[i]]; dp[i][j]=(a||b); } } } cout<<dp[5][12]<<endl; return 0; } dp其实就是选与不选的问题.
文章来源: 动态规划(dp)