动态规划经典例题

一、 01背包问题

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	int m, n;
	while(cin >> m >> n){
		vector<int> w(n+1, 0);//每个物品的体积
		vector<int> v(n+1, 0);//每个物品的价值
		for(int i = 1; i <= n; i++)
			cin >> w[i];
		for(int i = 1; i <= n; i++)
			cin >> v[i];
		vector<vector<int>> vec(n+1, vector<int>(m+1, 0));//价值二维数组
		for(int i = 1; i <= n; i++){//n是数量
			for(int j = 1; j <= m; j++){//m是体积
				if(w[i] > j)
					vec[i][j] = vec[i-1][j];
				else
					vec[i][j] = max(vec[i-1][j], vec[i-1][j-w[i]] + v[i]);
			}
		}
		cout << vec[n][m] << endl;
	}
	return 0;
}

二、最长公共子序列lcs

在这里插入图片描述

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
	string s1, s2;
	cin >> s1 >> s2;
	int len1 = s1.length();
	int len2 = s2.length();
	int c[len1+1][len2+1];
	for(int i = 0; i <= len1; i++){
		for(int j = 0; j <= len2; j++){
			if(i == 0 || j == 0)
				c[i][j] = 0;
			else if(s1[i-1] == s2[j-1])
				c[i][j] = c[i-1][j-1] + 1;
			else
				c[i][j] = max(c[i-1][j], c[i][j-1]);
		}
	}
	cout << c[len1][len2] << endl;
	return 0;
}

三、最长公共子串

在这里插入图片描述

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
	string s1, s2;
    cin >> s1 >> s2;
    int len1 = s1.length();
    int len2 = s2.length();
    int c[len1+1][len2+1];
    int result = 0;
    for(int i = 0; i <= len1; i++){
        for(int j = 0; j <= len2; j++){
            if(i ==0 || j == 0)
                c[i][j] = 0;
            else if(s1[i-1] == s2[j-1]){
                c[i][j] = c[i-1][j-1] + 1;
                result = max(c[i][j], result);
            }
            else
                c[i][j] = 0;

        }
    }
    cout<< result <<endl;
	return 0;
}

四、最长上升子序列

#include <iostream>
#include <algorithm>
using namespace std;
int a[1005];
int res[1005];
int main()
{
	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i];
		res[i] = 1;
	}
	for(int i = 1; i < n; i++){
		for(int j = 0; j < i; j++){
			if(a[j] < a[i])
				res[i] = max(res[i], res[j] + 1);
		}
	}
	cout << *max_element(res, res + n) << endl;
	return 0;
}

五、拿糖果

问题描述

妈妈给小B买了N块糖果,但他不允许小B直接吃掉。
假设当前有M块糖,小B每次可以拿p块糖,其中P是M的一个不大于根号下M的质因数。这时,妈妈就会在小B拿了P块糖以后再从糖堆里拿走P块糖。然后小B就可以接着拿糖
现在小B希望知道最多可以拿走多少糖。

解题思路

首先创建一个满足不大于根号下最大值MAXN的素数表,然后对素数表里的数逐个遍历
构建一个dp[i]数组,表示当糖果数量为i的时候所能拿的最多的糖果数量
对于dp[i] 的值:因为小B只能每次拿不大于根号下i的质因数,遍历素数表中满足条件的素数(prime[j] <= sqrt(i) && i % prime[j] == 0),更新dp[i]的值为(dp[i - 2 * prime[j]] + prime[j] )的最大值。
即: dp[i] = max(dp[i], dp[i - 2 * prime[j]] + prime[j]
这里的d[j - 2 * prime[j]] + prime[j] 表示拿走了prime[j] 块

代码

#include <iostream>
#include <math.h>
using namespace std;
int prime[50000];
int dp[100005];
int book[100005];
int cnt = 0;
void create() {
	int len = sqrt(100005);
	for(int i = 2; i <= len; i++) {
		if(book[i] == 0){
			prime[i] == i;
			for(int j = i * i; j <= len; j = j + i) {
				book[j] = 1;
			}
		}
	}
}
int main() {
	create();
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) {
		for(int j = 0; j < cnt; j++) {
			if(prime[j] > sqrt(i))
				break;
			if(i % prime[j] == 0) {
				int temp1 = dp[i]; //若不拿 prime[j]块
				int temp2 = dp[i - 2 * prime[j]] + prime[j]; //若拿 prime[j]块
				dp[i] = temp2 > temp1 ? temp2 : temp1;
			}	
		}
	}
	cout << dp[n];
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值