C++:动态规划DP基础&背包

U1:动态规划是什么

        动态规划,简称动规,是针对最优解问题的一种途径,而不是一种算法:

                1.它没有一个通用的解法

                2.往往是针对一种最优化问题,因而有许多不同的解题方法

        动态规划使用要满足什么条件:

                最优子结构和无后效性原则

                        最优子结构:

                                满足它是可以分解成几个最优子问题

                               

                        无后效性:这个子问题只会受到之前的答案影响

                可以分为几个阶段来完成

U2:动态规划例题

        数塔问题

登录 - 沐枫OJhttps://www.mfstem.org/p/524            这道题是一道经典的DP题

            没有学 DP 的你,是不是会有贪心的想法呢

        这明显不能用贪心

        那暴力呢?

        O(2^n)会超时,那就是dp了

        方程:f[i][j] = a[i][j] + max(f[i+1][j], f[i+1][j+1]);

        这是逆推的方法

        通过后一行算出的数据,得到这一行的数据

        赛马代码环节

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a[15][15],f[15][15];
signed main(){
	int n;
	cin >> n;
	for(int i = 1;i <= n;++i)
		for(int j = 1;j <= i;++j) {
			cin >> a[i][j];
			f[n][j] = a[i][j];//初始化
		}
	for(int i = n - 1;i >= 1;--i){
		for(int j = 1;j <= i;++j){
			f[i][j] = max(f[i + 1][j],f[i + 1][j + 1]) + a[i][j];//状态转移方程
		}
	}
	cout << f[1][1] << endl;	//答案
	return 0; //qwq
}

 U3:背包

        背包是DP的一个分支,分为01背包,完全背包,多重背包,分组背包

        这次先讲前两个

      T1:01背包

                顾名思义01背包就是没的东西可以拿一次或不拿

登录 - 沐枫OJhttps://www.mfstem.org/p/565

                这是二维的状态转移方程: 

f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + c[i]);

                f[i][j] 是前i个东西在容量为j的最大值,很容易理解吧,拿和不拿

                 我们发现,f[i][j]只跟f[i - 1][......]有关,我们可以优化为一维数组

f[j] = max(f[j],f[j - w[i]] + c[i]);

                上代码!!!

                二维:

#include<bits/stdc++.h>
using namespace std;
#define int long long
int w[40],c[40],f[40][210];
signed main(){
	int m,n;
	scanf("%lld%lld",&m,&n);
	for(int i = 1;i <= n;++i)scanf("%lld%lld",&w[i],&c[i]);
	for(int i = 1;i <= n;++i){
		for(int j = 0;j <= m;++j){
			if(j < w[i])f[i][j] = f[i - 1][j];
			else f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + c[i]);
		}
	}
	printf("%lld\n",f[n][m]);
	return 0;
}

                一维: 

#include<bits/stdc++.h>
using namespace std;
#define int long long
int w[40],c[40],f[210];
signed main(){
	int m,n;
	scanf("%lld%lld",&m,&n);
	for(int i = 1;i <= n;++i)scanf("%lld%lld",&w[i],&c[i]);
	for(int i = 1;i <= n;++i){
		for(int j = m;j >= w[i];--j){
			f[j] = max(f[j],f[j - w[i]] + c[i]);
		}
	}
	printf("%lld\n",f[m]);
	return 0;
}

        T2:完全背包

                       登录 - 沐枫OJhttps://www.mfstem.org/p/566                        完全背包,就是每种物品可以取无数个,问你最大值

                        方程:

f[i][v] = max(f[i - 1][v],f[i-1][v-k*w[i]]+k*c[i]);

                        可以改成

f[i][v] = max([i-1][v], f[i][v-w[i]] + c[i]);

                       

#include<bits/stdc++.h>
using namespace std;
int w[37],v[37],f[1005];
int main(void){
	int n,m;
	cin >> m >> n;
	for(int i = 1;i <= n;++i)cin >> w[i] >> v[i];
	for(int i = 1;i <= n;++i){
		for(int j = w[i];j <= m;++j){
			f[j] = max(f[j],f[j - w[i]] + v[i]);
		}
	}
	cout << "max=" << f[m] << endl;
	return 0;
}

end

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值