动态规划阶段性学习总结续

      关于最长大子段和问题,如果dp[i]是以a[i]为结尾的前i项的最大子段和,那么只需要考虑dp[i-1]的具体情况,如果大于0,则dp[i]=dp[i-1]+a[i],如果小于0,则最大子段和的起始位置更新,dp[i]=a[i];因为如果dp[i-1]小于0,子段和趋于减小,其与a[i]相加后的和比a[i]小。
     这一直是困扰我的地方,想了好久,就是感觉不通透,每天都看很多关于最大子段和的题目解析,都是一句话带过——易知。当绕过这个弯儿来,一切都明朗了。     
    以下是我自己写的最大子段和的代码实现,其中标注了起点和终点,其实还可以改成起始元素和终止元素本身。
    #include <iostream>
    #include <cstring>
    using namespace std;
    int a[10001],dp[10001];
    int main()
    {	
    int n;	
    cin>>n;
    for(int i = 1;i<=n;i++)
    		cin>>a[i];
   	int sum = 0,s=1,e = 1;	
   	dp[1] = max(a[1],0);	
   	for(int i = 2;i<=n;i++)
  	{
  		if(dp[i-1]<0)	
  			{	
  					dp[i] = a[i];
  						s = i;	
  			}		
  		else		
  		   {	
  		     		dp[i] = dp[i-1]+a[i];		
  		    }	
      }
   	  for(int i = 1;i<=n;i++)		
   	  if(sum<dp[i])		
   	  {	
   	  		sum=dp[i];	
   	  		e=i;	
   	  	}	
   	  	cout<<sum<<" "<<s<<" "<<e<<endl;	
   	  	return 0;
   	 }          
   	 今天班里去春游,很累,但是还是勉强看完了0-1背包问题,基本原理已经搞懂,记录每次放入背包的价值总和,和背包当前的价值比较,加和最大值。其实算法图解中还有一个很好的解析,图文结合,原理明了。          粗略的写了一下代码。
   	 #include <iostream>
   	 #include <cstdio>
   	 #include <cstring>
   	 #include <algorithm>
   	 using namespace std;
   	 int c[10001];int v[10001];
   	 int f[10001];
   	 int main()
   	 {	
   	 int t,n,x;//n为数量,x为容积	
   	 cin>>t;
    while(t--)	
    {
    		cin>>n>>x;
    		memset(f,0,sizeof(f));		
    		for(int i = 0;i<n;i++)			
    		cin>>v[i];		
    		for(int i = 0;i<n;i++)			
    		cin>>c[i];		
    		for(int i = 0;i<n;i++)
    					for(int j = x;j>=c[i];j--)
    								f[j] = max(f[j-c[i]]+v[i],f[j]);
    								cout<<f[x]<<endl;	
    }	
    return 0;

}
开始感觉做dp的乐趣所在,就那么几个问题,翻来覆去的变,但原理都一样,套用上基本代码,稍作修改,好多题都可以AC,。另外继续肝,重在平时,每天两道题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值