POJ 1976

題意:迷你火車頭拉人,看一次最多能拉多少人。

    題目要求輸入車廂數,每節車廂的人數,以及每個迷你火車頭能拉動車箱的數目,要求輸出三個迷你火車頭能拉動的最多人數。

 

01揹包問題:

http://love-oriented.com/pack/P01.html

 

http://baike.baidu.com/view/841810.htm

 

動態規劃是用空間換時間的一種方法的抽象。其關鍵是發現子問題和記錄其結果。然後利用這些結果減輕運算量。
比如01揹包問題。

因爲揹包最大容量M未知。所以,我們的程序要從1到M一個一個的試。比如,開始任選N件物品的一個。看對應M的揹包,能不能放進去,如果能放進去,並且還有多的空間,則,多出來的空間裏能放N-1物品中的最大價值。怎麼能保證總選擇是最大價值呢?看下錶。
測試數據:
10,3
3,4
4,5
5,6

POJ <wbr>1976

c[i][j]數組保存了1,2,3號物品依次選擇後的最大價值.

這個最大價值是怎麼得來的呢?從揹包容量爲0開始,1號物品先試,0,1,2,的容量都不能放.所以置0,揹包容量爲3則裏面放4.這樣,這一排揹包容量爲4,5,6,....10的時候,最佳方案都是放4.假如1號物品放入揹包.則再看2號物品.當揹包容量爲3的時候,最佳方案還是上一排的最價方案c爲4.而揹包容量爲5的時候,則最佳方案爲自己的重量5.揹包容量爲7的時候,很顯然是5加上一個值了。加誰??很顯然是7-4=3的時候.上一排c3的最佳方案是4.所以。總的最佳方案是5+4爲9.這樣.一排一排推下去。最右下放的數據就是最大的價值了。(注意第3排的揹包容量爲7的時候,最佳方案不是本身的6.而是上一排的9.說明這時候3號物品沒有被選.選的是1,2號物品.所以得9.)

從以上最大價值的構造過程中可以看出。

f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}這就是書本上寫的動態規劃方程.

 

 

 

代碼:

#include<iostream>
using namespace std;
int main()
{
   int n,co,lom,k,*pa,*cpa,**mmax;  //co:車廂數,lom:每個迷你火車頭所能拉動的車廂數,pa數組:每個車廂裏的人數,cpa數組:從1到co-lom+1裏,每lom節車廂的人數,mmax數組:三節迷你火車頭所能拉動的最大總人數。
   cin>>n;
   while(n--)
   {
       cin>>co;
       pa=new int[co+1];
       for(int i=1;i<=co;i++)cin>>pa[i];
       cin>>lom;
       cpa=new int[co-lom+2];
       mmax=new int*[co-lom+2];
       for(int i=0;i<co-lom+2;i++)
       {
           mmax[i]=new int[4];
           for(int j=0;j<4;j++)
               mmax[i][j]=0;
       }
       memset(cpa,0,(co-lom+2)*sizeof(int));
       for(int i=1;i<=co-lom+1;i++)
           for(int j=i;j<i+lom;j++)
               cpa[i]+=pa[j];
       for(int i=1;i<=co-lom+1;i++)
           for(int j=1;j<=3;j++)
           {
               if(i-lom<0)k=0;
               else k=i-lom;
               mmax[i][j]=max(mmax[i-1][j],mmax[k][j-1]+cpa[i]);
           }
       cout<<mmax[co-lom+1][3]<<endl;
       delete []pa;
       delete []cpa;
       for(int i=0;i<co-lom+2;i++)
           delete []mmax[i];
       delete []mmax;
   }
   return 0;
}

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