动态规划

/*  1)动态规划的基本思想:将复杂问题进行分解简化,通过去求解
        小规模子问题反推出原问题的结果。动态规划适合求解多阶
        段决策问题的最优解(可以简单理解为有状态转换的阶段性
        问题)。这些问题必须满足最优化原理和子问题的无后向性。
    2)两个要素:最优子结构性质和子问题重叠性质。
        1.最优子结构:
                如果问题的最优解所包含的子问题的解也是最优的,
            我们就称该问题具有最优子结构性质(即满足最优化原
            理)。意思就是,总问题包含很多个子问题,而这些子
            问题的解也是最优的。
        2.重叠子问题:
                子问题重叠性质是指在用递归算法自顶向下对问题
            进行求解时,每次产生的子问题并不总是新问题,有些
            子问题会被重复计算多次。动态规划算法正是利用了这
            种子问题的重叠性质,对每一个子问题只计算一次,然
            后将其计算结果保存在一个表格中,当再次需要计算已
            经计算过的子问题时,只是在表格中简单地查看一下结
            果,从而获得较高的效率。
    3)动态规划算法的基本步骤:
        1.将原问题分解为子问题(子问题和原问题形式相同,且子问题解求出就会被保存);
      2.确定状态:比如在01背包中一个状态就是个物体中第个是否放入体积为背包中;
      3.确定一些初始状态(边界状态)的值;
      4.确定状态转移方程,如何从一个或多个已知状态求出另一个未知状态的值。(递推型)*/
/*最长公共子序列(longest common sequence)和最长
公共子串(longest common substring)不一样子序列:
即一个给定的序列的子序列,就是将给定序列中零个或
多个元素去掉之后得到的结果子串:给定串中任意个连续
的字符组成的子序列称为该串的子串*/
/*lcs
#include <iostream>
#include <cstring>
using namespace std;
#define NUM 1010
int c[NUM][NUM];
int b[NUM][NUM];
void LCS_LENGTH(string X, string Y);
void PRINT_LCS(string X,int m, int n);
int main()
{
	string X, Y;
	cin >> X >> Y;
	LCS_LENGTH(X, Y);
	PRINT_LCS(X,X.length(), Y.length());
	return 0;
}
void LCS_LENGTH(string X, string Y)
{
	int m = X.length();
	int n = Y.length();
	for (int i = 0; i <= m; i++)
		c[i][0] = 0;
	for (int j = 0; j <= n; j++)
		c[0][j] = 0;
	for (int i = 1; i <= m; i++){
		for (int j = 1; j <= n; j++){
			if (X[i - 1] == Y[j - 1]){
				c[i][j] = c[i - 1][j - 1] + 1;
				b[i][j] = 1;
			}
			else if (c[i - 1][j] >= c[i][j - 1]){
				c[i][j] = c[i - 1][j];
				b[i][j] = 2;
			}
			else{
				c[i][j] = c[i][j - 1];
				b[i][j] = 3;
			}
		}
	}
}

void PRINT_LCS(string X,int m, int n)
{
	if (m == 0 || n == 0)
		return;
	if (b[m][n] == 1){
		PRINT_LCS(X,m - 1, n - 1);
		cout << X[m-1];
	}
	else if (b[m][n] == 2){
		PRINT_LCS(X, m - 1, n);
	}
	else
		PRINT_LCS(X, m, n - 1);
}*/
//背包问题
/*#include <iostream>
using namespace std;
#define m 10010
int v[110][m]={0};
int max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int n,w,i,j;
    cin>>n>>w;
    int a[n+1],b[n+1];
    for(i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i];
    }
    for(i=0;i<=n;i++)
    {
        v[i][0]=0;
    }
    for(j=0;j<=w;j++)
    {
        v[0][j]=0;
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=w;j++)
        {
            if(j<a[i]) v[i][j]=v[i-1][j];
            else v[i][j]=max(v[i-1][j],v[i-1][j-a[i]]+b[i]);
        }
    }
    int mmm=0;
    for(i=0;i<=n;i++)
    {
        for(j=0;j<=w;j++)
        {
            if(v[i][j]>=mmm)
            {
                mmm=v[i][j];
            }
        }
    }
    cout<<mmm<<endl;
    return 0;
}*/
/*数字三角形
记忆化搜索
#include <iostream>
#include <algorithm>
using namespace std;
#define m 1000
int n;
int a[m][m];
int b[m][m];
int solve(int i,int j);
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<=i;j++)
        {
            cin>>a[i][j];
            b[i][j]=-1;
        }
    }
    int z=solve(0,0);
    cout<<z<<endl;
    return 0;
}
int solve(int i,int j)
{
    if(b[i][j]!=-1) return b[i][j];
    if(i==n-1) return b[i][j]=a[i][j]+0;
    return b[i][j]=a[i][j]+max(solve(i+1,j),solve(i+1,j+1));
}*/
/*递推
int i,j;
for(int j=0;j<n;j++)
{
    b[n-1][j]=a[n-1][j];
}
for(int i=n-2;i>=0;i--)
{
    for(int j=0;j<=i;j++)
    {
        b[i][j]=max(b[i+1][j],b[i+1][j+1]);
    }
}*/
/*#include <iostream>
#include <algorithm>
using namespace std;
#define m 10010
int t,i,j,n;
struct jx
{
    int x,y;
}a[m];
int b[m][m]={0},c[m]={0};
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=0;i<n;i++)
        {
            cin>>a[i].x>>a[i].y;
            if(a[i].x>a[i].y) swap(a[i].x,a[i].y);
        }
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                if(a[i].x>a[j].x&&a[i].y>a[j].y) b[i][j]=1;
            }
        }
        for(i=0;i<n;i++)
        {

        }

    }
}
int dpdag(int i)
{
    if(c[i]>0) return c[i];
    c[i]=1;
    for(j=0;j<n;j++)
    {
        if(b[i][j]==1) c[m]=c[m]>dpdag(j)+1?c[m]:dpdag(j)+1;
    }
    return b[i];
}*/
/*最大字段和
#include <iostream>
using namespace std;
int main()
{
    int n,i;
    cin>>n;
    int a[n];
    long long int b[n],max=0;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
    }
    b[0]=a[0];
    for(i=1;i<n;i++)
    {
        if(b[i-1]>0)
            b[i]=b[i-1]+a[i];
        else b[i]=a[i];
        if(b[i]>max)
            max=b[i];
    }
    cout<<max<<endl;
    return 0;
}*/
/*P1060 开心的金明
#include <iostream>
#include <cstring>
using namespace std;
int a[30][30000+10];
int maxn(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    int n,m;
    cin>>n>>m;
    int q[m+1]={0},z[m+1]={0};
    for(int i=1;i<=m;i++)
        cin>>q[i]>>z[i];
    memset(a,0,sizeof(a));
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(j<q[i]) a[i][j]=a[i-1][j];
            else a[i][j]=maxn(a[i-1][j],a[i-1][j-q[i]]+q[i]*z[i]);
        }
    }
    cout<<a[m][n]<<endl;
    return 0;
}*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值