动态规划(2)

动态规划一般只能应用于有最优子结构的问题。
最优子结构的意思是局部最优解能决定全局最
优解(对有些问题这个要求并不能完全满足,
故有时需要引入一定的近似)。简单地说,问
题能够分解成子问题来解决。
动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、
判断是否满足最优性原理、找大问题与小问题的递推关系式、
填表、寻找解组成,然后编写代码实现)
动态规划算法分以下4个步骤:
1.描述最优解的结构
2.递归定义最优解的值
3.按自底向上的方式计算最优解的值 //此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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值