各种dp题解(持续更新)

本蒟蒻在练习DP中~

所以开个博客记录dp的题解~

欢迎关注~也欢迎各路julao吐槽代码qwq

难度什么的我刷到一定量的时候再打上

题面请点蓝色的字~

为了方便食用我就不贴头文件了(逃

其实根本不算题解啊(很少讲解)

DP介绍

动态规划是运筹学的一个分支,是求解决策过程最优化的数学方法。利用各个阶段之间的关系,逐个求解,最终求得全局最优解,需要确认原问题与子问题、动态规划状态、边界状态、边界状态结值、状态转移方程。

T1:

最大子段和

分析:

这道题的子问题是什么,我们怎么刻画这件事?首先,把子问题看作求 前i个数中的最大子段和 是不可以的,因为这个描述并不足以刻画“连续”这一点,比如说,你求出了前5个数最大子段和是114,但是这个子段和却是由第2,3,4个数组成的,那么刻画5+1时候的方程就会出现不妥(即dp[i+1]无法刻画)。

因此,dp[i]应该被描述成子段带有第i个元素(或全部都不取(也就是0))的子段最大值,这样就可以描述“连续”这件事了。

据此,dp方程如下:

dp[i]=max(max(0,a[i]),dp[i-1]+a[i]);

下面贴出代码:

int a[maxn];
int dp[maxn];
int main(){
	int n;cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	
	if(*max_element(a+1,a+n+1)<0){
		cout<<*max_element(a+1,a+n+1); 
		return 0;
	}//特判,这里很重要!!!要是全部是负数不可以输出0(因为子段非空)
	
	for(int i=1;i<=n;i++)dp[i]=max(max(0,a[i]),dp[i-1]+a[i]);
	int ans=*max_element(dp+1,dp+n+1); 
	cout<<ans<<endl;
	return 0;
}

T2:

采药

这就是一道01背包DP的裸题嘛~

不会01背包DP的同学就去学(逃

分析:子问题:前i件物品放入体积为j的背包,求可能获得的最大价值

方程:读者可以李姐李姐 其实就是在取和不取之间的情况找一个最大值

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

code(二维):

int c[101];//物品体积
int w[101];//物品价值
int dp[101][10001]; 
int t,n;//t表示背包容量,n表示物品数量 
int main(){
	cin>>t>>n;
	for(int i=1;i<=n;i++)
	cin>>c[i]>>w[i];
	
	for(int i=1;i<=n;i++){
		for(int j=t;j>=1;j--){
			if(j>=c[i]) dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i]);
			else dp[i][j]=dp[i-1][j];
		} 
	}
	cout<<dp[n][t];		
	return 0;
}

当然一维也是可以的~


int c[101];//物品体积
int w[101];//物品价值
int dp[10001]; 
int t,n;//t表示背包容量,n表示物品数量 
int main(){
	cin>>t>>n;
	for(int i=1;i<=n;i++)
	cin>>c[i]>>w[i];
	
	for(int i=1;i<=n;i++){
		for(int j=t;j>=c[i];j--){
			dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
		} 
	}
	cout<<dp[t];		
	return 0;
}

T3

疯狂的采药

多重背包的裸题~

注意:不开long long见祖宗(亲测


typedef unsigned long long ll;
ll c[10000+5];//物品体积
ll w[10000+5];//物品价值
ll dp[10000000+5]; 
ll t,n;//t表示背包容量,n表示物品数量 
int main(){
	cin>>t>>n;
	for(int i=1;i<=n;i++)
	cin>>c[i]>>w[i];
	
	for(int i=1;i<=n;i++){
		for(int j=c[i];j<=t;j++){
			dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
		} 
	}
	cout<<dp[t];		
	return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值