动态规划

动态规划
采用动态规划求解的问题需要具有两个特性:
  • 最优子结构(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++;
			else
				count = 1;
			res = max(res, count);
		}
		cout << res << endl;
	}
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值