动态规划

来源:互联网 发布:王朔人品知乎 编辑:程序博客网 时间:2024/06/16 21:45
动态规划
采用动态规划求解的问题需要具有两个特性:
  • 最优子结构(Optimal Substructure):问题的一个最优解中所包含的子问题的解也是最优的。
  • 重叠子问题(Overlapping Subproblems):用递归算法对问题进行求解时,每次产生的子问题并不总是新问题,有些子问题会被重复计算多次。
综上所述,动态规划的关键是 —— 记忆,空间换时间,不重复求解,从较小问题解逐步决策,构造较大问题的解。

1、动态规划一般可分为线性规划、区域规划、树形规划、背包动态规划四类。
2、动态规划两个重要概念:状态和状态转移方程。
3、最长公共子串、最长公共子序列、最长递增子序列。
最长公共子串最长公共子序列的区别:子串要求在原字符串中是连续的,而子序列则只需保持相对顺序,并不要求连续。
最长公共子序列(LSC)
#include<iostream>#include<algorithm>#include<vector>#include<string>using namespace std;int array[2000][2000];int dp[2000][2000];int main(){//有两条随机序列,如 1 3 4 5 5 6 和 2 4 5 5 7 6,则它们的最长公共子序列便是:4 5 5 6,最长公共子串为4 5 5。     string str1, str2;     memset(dp, 0, sizeof(dp));     while (cin >> str1 >> str2)     {         int la = str1.length();//字符串1的长度         int lb = str2.length();//字符串2的长度         for (int idx = 1; idx <= la; idx++)         {              for (int jdx = 1; jdx <= lb; jdx++)              {                  if (str1[idx-1] == str2[jdx-1])//两个字符串中有相同的字符                  {                       dp[idx][jdx] = dp[idx - 1][jdx - 1] + 1;                  }                  else                       dp[idx][jdx] = max(dp[idx - 1][jdx], dp[idx][jdx - 1]);              }         }         cout << dp[la][lb] << endl;//统计子字符序列的个数     }     system("pause");     return 0;}
最长公共子串
#include<iostream>#include<algorithm>#include<vector>#include<string>using namespace std;int array[2000][2000];int dp[2000][2000];int main(){         string str1, str2;         memset(dp, 0, sizeof(dp));         while (cin >> str1 >> str2)         {              int biggest = 0;              int la = str1.length();//字符串1的长度              int lb = str2.length();//字符串2的长度              for (int idx = 1; idx <= la; idx++)              {                  for (int jdx = 1; jdx <= lb; jdx++)                  {                       if (str1[idx-1] == str2[jdx-1])//两个字符串中有相同的字符                       {                            dp[idx][jdx] = dp[idx - 1][jdx - 1] + 1;                            if (dp[idx][jdx] > biggest)                                biggest = dp[idx][jdx];                       }                       else                            dp[idx][jdx] = 0;                  }              }              cout << biggest << endl;//统计子串序列的个数         }     system("pause");     return 0;}
最长递增子序列(LIC)
#include<iostream>#include<algorithm>#include<vector>#include<string>using namespace std;int main(){     int n = 0;     int dp[1000];//存放子序列中数字的个数     int arr[1000];//序列     while (cin >> n)     {         int res = 0;         memset(arr, 0, sizeof(arr));         memset(dp, 0, sizeof(dp));         for (int idx = 0; idx < n; idx++)              cin >> arr[idx];         for (int idx = 0; idx < n; idx++)         {              dp[idx] = 1;              for (int jdx = 0; jdx < idx; jdx++)              {                  if (arr[idx] > arr[jdx])                       dp[idx] = max(dp[idx], dp[jdx] + 1);              }              res = max(res, dp[idx]);         }         cout << res << endl;     }return 0;}
最长递增子串
#include<iostream>#include<algorithm>#include<queue>using namespace std;int main(){//最长递增子串int n = 0;int arr[1000];//序列queue<int> q;while (cin >> n){int res = 0;int count = 1;memset(arr, 0, sizeof(arr));for (int idx = 0; idx < n; idx++){cin >> arr[idx];q.push(arr[idx]);}while (!q.empty()){int temp = q.front();q.pop();if (q.size() && temp < q.front())count++;elsecount = 1;res = max(res, count);}cout << res << endl;}system("pause");return 0;}

原创粉丝点击