動態規劃階段性學習總結續

      關於最長大子段和問題,如果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,。另外繼續肝,重在平時,每天兩道題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章